Index: clang/include/clang/AST/Expr.h
===================================================================
--- clang/include/clang/AST/Expr.h
+++ clang/include/clang/AST/Expr.h
@@ -4686,13 +4686,14 @@
 };
 
 /// Represents a function call to one of __builtin_LINE(), __builtin_COLUMN(),
-/// __builtin_FUNCTION(), __builtin_FILE(), or __builtin_source_location().
+/// __builtin_FUNCTION(), __builtin_FILE(), builtin_FILE_NAME(),
+/// or __builtin_source_location().
 class SourceLocExpr final : public Expr {
   SourceLocation BuiltinLoc, RParenLoc;
   DeclContext *ParentContext;
 
 public:
-  enum IdentKind { Function, File, Line, Column, SourceLocStruct };
+  enum IdentKind { Function, File, FileName, Line, Column, SourceLocStruct };
 
   SourceLocExpr(const ASTContext &Ctx, IdentKind Type, QualType ResultTy,
                 SourceLocation BLoc, SourceLocation RParenLoc,
@@ -4716,6 +4717,7 @@
   bool isIntType() const {
     switch (getIdentKind()) {
     case File:
+    case FileName:
     case Function:
     case SourceLocStruct:
       return false;
Index: clang/include/clang/Basic/TokenKinds.def
===================================================================
--- clang/include/clang/Basic/TokenKinds.def
+++ clang/include/clang/Basic/TokenKinds.def
@@ -436,6 +436,7 @@
 KEYWORD(__builtin_choose_expr       , KEYALL)
 KEYWORD(__builtin_offsetof          , KEYALL)
 KEYWORD(__builtin_FILE              , KEYALL)
+KEYWORD(__builtin_FILE_NAME         , KEYALL)
 KEYWORD(__builtin_FUNCTION          , KEYALL)
 KEYWORD(__builtin_LINE              , KEYALL)
 KEYWORD(__builtin_COLUMN            , KEYALL)
Index: clang/include/clang/Lex/Preprocessor.h
===================================================================
--- clang/include/clang/Lex/Preprocessor.h
+++ clang/include/clang/Lex/Preprocessor.h
@@ -2855,6 +2855,11 @@
                                       const LangOptions &LangOpts,
                                       const TargetInfo &TI);
 
+  static void processPathToFileName(SmallVectorImpl<char> &FileName,
+                                    const PresumedLoc &PLoc,
+                                    const LangOptions &LangOpts,
+                                    const TargetInfo &TI);
+
 private:
   void emitMacroDeprecationWarning(const Token &Identifier) const;
   void emitRestrictExpansionWarning(const Token &Identifier) const;
Index: clang/lib/AST/Expr.cpp
===================================================================
--- clang/lib/AST/Expr.cpp
+++ clang/lib/AST/Expr.cpp
@@ -2239,6 +2239,8 @@
   switch (getIdentKind()) {
   case File:
     return "__builtin_FILE";
+  case FileName:
+    return "__builtin_FILE_NAME";
   case Function:
     return "__builtin_FUNCTION";
   case Line:
@@ -2277,6 +2279,14 @@
   };
 
   switch (getIdentKind()) {
+  case SourceLocExpr::FileName: {
+    // builtin_FILE_NAME() is a Clang-specific extension that expands to the
+    // the last part of builtin_FILE().
+    SmallString<256> FileName;
+    clang::Preprocessor::processPathToFileName(
+        FileName, PLoc, Ctx.getLangOpts(), Ctx.getTargetInfo());
+    return MakeStringLiteral(FileName);
+  }
   case SourceLocExpr::File: {
     SmallString<256> Path(PLoc.getFilename());
     clang::Preprocessor::processPathForFileMacro(Path, Ctx.getLangOpts(),
Index: clang/lib/Lex/PPMacroExpansion.cpp
===================================================================
--- clang/lib/Lex/PPMacroExpansion.cpp
+++ clang/lib/Lex/PPMacroExpansion.cpp
@@ -1559,17 +1559,11 @@
       // __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();
+        processPathToFileName(FN, PLoc, getLangOpts(), getTargetInfo());
       } else {
         FN += PLoc.getFilename();
+        processPathForFileMacro(FN, getLangOpts(), getTargetInfo());
       }
-      processPathForFileMacro(FN, getLangOpts(), getTargetInfo());
       Lexer::Stringify(FN);
       OS << '"' << FN << '"';
     }
@@ -1995,3 +1989,17 @@
       llvm::sys::path::remove_dots(Path, false, llvm::sys::path::Style::posix);
   }
 }
+
+void Preprocessor::processPathToFileName(SmallVectorImpl<char> &FileName,
+                                         const PresumedLoc &PLoc,
+                                         const LangOptions &LangOpts,
+                                         const TargetInfo &TI) {
+  // Try to get the last path component, failing that return the original
+  // presumed location.
+  StringRef PLFileName = llvm::sys::path::filename(PLoc.getFilename());
+  if (PLFileName.empty()) {
+    PLFileName = PLoc.getFilename();
+  }
+  FileName.append(PLFileName.begin(), PLFileName.end());
+  processPathForFileMacro(FileName, LangOpts, TI);
+}
Index: clang/lib/Parse/ParseExpr.cpp
===================================================================
--- clang/lib/Parse/ParseExpr.cpp
+++ clang/lib/Parse/ParseExpr.cpp
@@ -789,6 +789,7 @@
 /// [GNU]   '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
 ///                                     assign-expr ')'
 /// [GNU]   '__builtin_FILE' '(' ')'
+/// [CLANG] '__builtin_FILE_NAME' '(' ')'
 /// [GNU]   '__builtin_FUNCTION' '(' ')'
 /// [GNU]   '__builtin_LINE' '(' ')'
 /// [CLANG] '__builtin_COLUMN' '(' ')'
@@ -801,20 +802,18 @@
 /// [OBJC]  '\@encode' '(' type-name ')'
 /// [OBJC]  objc-string-literal
 /// [C++]   simple-type-specifier '(' expression-list[opt] ')'      [C++ 5.2.3]
-/// [C++11] simple-type-specifier braced-init-list                  [C++11 5.2.3]
-/// [C++]   typename-specifier '(' expression-list[opt] ')'         [C++ 5.2.3]
-/// [C++11] typename-specifier braced-init-list                     [C++11 5.2.3]
-/// [C++]   'const_cast' '<' type-name '>' '(' expression ')'       [C++ 5.2p1]
-/// [C++]   'dynamic_cast' '<' type-name '>' '(' expression ')'     [C++ 5.2p1]
-/// [C++]   'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
-/// [C++]   'static_cast' '<' type-name '>' '(' expression ')'      [C++ 5.2p1]
-/// [C++]   'typeid' '(' expression ')'                             [C++ 5.2p1]
-/// [C++]   'typeid' '(' type-id ')'                                [C++ 5.2p1]
-/// [C++]   'this'          [C++ 9.3.2]
-/// [G++]   unary-type-trait '(' type-id ')'
-/// [G++]   binary-type-trait '(' type-id ',' type-id ')'           [TODO]
-/// [EMBT]  array-type-trait '(' type-id ',' integer ')'
-/// [clang] '^' block-literal
+/// [C++11] simple-type-specifier braced-init-list [C++11 5.2.3] [C++]
+/// typename-specifier '(' expression-list[opt] ')'         [C++ 5.2.3] [C++11]
+/// typename-specifier braced-init-list                     [C++11 5.2.3] [C++]
+/// 'const_cast' '<' type-name '>' '(' expression ')'       [C++ 5.2p1] [C++]
+/// 'dynamic_cast' '<' type-name '>' '(' expression ')'     [C++ 5.2p1] [C++]
+/// 'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] [C++]
+/// 'static_cast' '<' type-name '>' '(' expression ')'      [C++ 5.2p1] [C++]
+/// 'typeid' '(' expression ')'                             [C++ 5.2p1] [C++]
+/// 'typeid' '(' type-id ')'                                [C++ 5.2p1] [C++]
+/// 'this'          [C++ 9.3.2] [G++]   unary-type-trait '(' type-id ')' [G++]
+/// binary-type-trait '(' type-id ',' type-id ')'           [TODO] [EMBT]
+/// array-type-trait '(' type-id ',' integer ')' [clang] '^' block-literal
 ///
 ///       constant: [C99 6.4.4]
 ///         integer-constant
@@ -1317,6 +1316,7 @@
   case tok::kw___builtin_convertvector:
   case tok::kw___builtin_COLUMN:
   case tok::kw___builtin_FILE:
+  case tok::kw___builtin_FILE_NAME:
   case tok::kw___builtin_FUNCTION:
   case tok::kw___builtin_LINE:
   case tok::kw___builtin_source_location:
@@ -2542,6 +2542,7 @@
 ///                                     assign-expr ')'
 /// [GNU]   '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
 /// [GNU]   '__builtin_FILE' '(' ')'
+/// [CLANG] '__builtin_FILE_NAME' '(' ')'
 /// [GNU]   '__builtin_FUNCTION' '(' ')'
 /// [GNU]   '__builtin_LINE' '(' ')'
 /// [CLANG] '__builtin_COLUMN' '(' ')'
@@ -2777,6 +2778,7 @@
   }
   case tok::kw___builtin_COLUMN:
   case tok::kw___builtin_FILE:
+  case tok::kw___builtin_FILE_NAME:
   case tok::kw___builtin_FUNCTION:
   case tok::kw___builtin_LINE:
   case tok::kw___builtin_source_location: {
@@ -2790,6 +2792,8 @@
       switch (T) {
       case tok::kw___builtin_FILE:
         return SourceLocExpr::File;
+      case tok::kw___builtin_FILE_NAME:
+        return SourceLocExpr::FileName;
       case tok::kw___builtin_FUNCTION:
         return SourceLocExpr::Function;
       case tok::kw___builtin_LINE:
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -17045,6 +17045,7 @@
   QualType ResultTy;
   switch (Kind) {
   case SourceLocExpr::File:
+  case SourceLocExpr::FileName:
   case SourceLocExpr::Function: {
     QualType ArrTy = Context.getStringLiteralArrayType(Context.CharTy, 0);
     ResultTy =
Index: clang/test/Preprocessor/feature_tests.c
===================================================================
--- clang/test/Preprocessor/feature_tests.c
+++ clang/test/Preprocessor/feature_tests.c
@@ -24,6 +24,7 @@
 // still return true.
 #if !__has_builtin(__builtin_LINE) || \
     !__has_builtin(__builtin_FILE) || \
+    !__has_builtin(__builtin_FILE_NAME) || \
     !__has_builtin(__builtin_FUNCTION) || \
     !__has_builtin(__builtin_COLUMN) || \
     !__has_builtin(__builtin_types_compatible_p)
Index: clang/test/Preprocessor/feature_tests.cpp
===================================================================
--- clang/test/Preprocessor/feature_tests.cpp
+++ clang/test/Preprocessor/feature_tests.cpp
@@ -23,6 +23,7 @@
 // still return true.
 #if !__has_builtin(__builtin_LINE) || \
     !__has_builtin(__builtin_FILE) || \
+    !__has_builtin(__builtin_FILE_NAME) || \
     !__has_builtin(__builtin_FUNCTION) || \
     !__has_builtin(__builtin_COLUMN) || \
     !__has_builtin(__array_rank) || \
Index: clang/test/Sema/source_location.c
===================================================================
--- clang/test/Sema/source_location.c
+++ clang/test/Sema/source_location.c
@@ -17,12 +17,14 @@
 
 #ifdef CONST_STRINGS
 _Static_assert(IsEqual(__builtin_FILE(), __FILE__), "");
+_Static_assert(IsEqual(__builtin_FILE_NAME(), __FILE_NAME__), "");
 _Static_assert(__builtin_LINE() == __LINE__, "");
 _Static_assert(IsEqual("", __builtin_FUNCTION()), "");
 
 #line 42 "my_file.c"
 _Static_assert(__builtin_LINE() == 42, "");
 _Static_assert(IsEqual(__builtin_FILE(), "my_file.c"), "");
+_Static_assert(IsEqual(__builtin_FILE_NAME(), "my_file.c"), "");
 
 _Static_assert(__builtin_COLUMN() == __builtin_strlen("_Static_assert(_"), "");
 
Index: clang/test/SemaCXX/Inputs/source-location-file.h
===================================================================
--- clang/test/SemaCXX/Inputs/source-location-file.h
+++ clang/test/SemaCXX/Inputs/source-location-file.h
@@ -4,8 +4,10 @@
 namespace source_location_file {
 
 constexpr const char *FILE = __FILE__;
+constexpr const char *FILE_NAME = __FILE_NAME__;
 
 constexpr SL global_info = SL::current();
+constexpr const char *global_info_filename = __builtin_FILE_NAME();
 
 constexpr SL test_function(SL v = SL::current()) {
   return v;
@@ -15,6 +17,15 @@
   return test_function();
 }
 
+constexpr const char *test_function_filename(
+                      const char *file_name = __builtin_FILE_NAME()) {
+  return file_name;
+}
+
+constexpr const char *test_function_filename_indirect() {
+  return test_function_filename();
+}
+
 template <class T, class U = SL>
 constexpr U test_function_template(T, U u = U::current()) {
   return u;
@@ -25,13 +36,29 @@
   return test_function_template(t);
 }
 
+template <class T, class U = const char *>
+constexpr U test_function_filename_template(T, U u = __builtin_FILE_NAME()) {
+  return u;
+}
+
+template <class T, class U = const char *>
+constexpr U test_function_filename_template_indirect(T t) {
+  return test_function_filename_template(t);
+}
+
 struct TestClass {
   SL info = SL::current();
+  const char *info_file_name = __builtin_FILE_NAME();
   SL ctor_info;
+  const char *ctor_info_file_name = nullptr;
   TestClass() = default;
-  constexpr TestClass(int, SL cinfo = SL::current()) : ctor_info(cinfo) {}
+  constexpr TestClass(int, SL cinfo = SL::current(),
+                      const char *cfile_name = __builtin_FILE_NAME()) :
+                      ctor_info(cinfo), ctor_info_file_name(cfile_name) {}
   template <class T, class U = SL>
-  constexpr TestClass(int, T, U u = U::current()) : ctor_info(u) {}
+  constexpr TestClass(int, T, U u = U::current(),
+                      const char *cfile_name = __builtin_FILE_NAME()) :
+                      ctor_info(u), ctor_info_file_name(cfile_name) {}
 };
 
 template <class T = SL>
@@ -39,6 +66,7 @@
   int x;
   T info;
   T init_info = T::current();
+  const char *init_info_file_name = __builtin_FILE_NAME();
 };
 
 } // namespace source_location_file
Index: clang/test/SemaCXX/source_location.cpp
===================================================================
--- clang/test/SemaCXX/source_location.cpp
+++ clang/test/SemaCXX/source_location.cpp
@@ -84,6 +84,7 @@
 static_assert(is_same<decltype(__builtin_LINE()), unsigned>);
 static_assert(is_same<decltype(__builtin_COLUMN()), unsigned>);
 static_assert(is_same<decltype(__builtin_FILE()), const char *>);
+static_assert(is_same<decltype(__builtin_FILE_NAME()), const char *>);
 static_assert(is_same<decltype(__builtin_FUNCTION()), const char *>);
 static_assert(is_same<decltype(__builtin_source_location()), const std::source_location::public_impl_alias *>);
 
@@ -91,6 +92,7 @@
 static_assert(noexcept(__builtin_LINE()));
 static_assert(noexcept(__builtin_COLUMN()));
 static_assert(noexcept(__builtin_FILE()));
+static_assert(noexcept(__builtin_FILE_NAME()));
 static_assert(noexcept(__builtin_FUNCTION()));
 static_assert(noexcept(__builtin_source_location()));
 
@@ -346,6 +348,54 @@
 
 } // namespace test_file
 
+//===----------------------------------------------------------------------===//
+//                            __builtin_FILE_NAME()
+//===----------------------------------------------------------------------===//
+
+namespace test_file_name {
+constexpr const char *test_file_name_simple(
+  const char *__f = __builtin_FILE_NAME()) {
+  return __f;
+}
+void test_function() {
+#line 900
+  static_assert(is_equal(test_file_name_simple(), __FILE_NAME__));
+  static_assert(is_equal(SLF::test_function_filename(), __FILE_NAME__), "");
+  static_assert(is_equal(SLF::test_function_filename_template(42),
+                         __FILE_NAME__), "");
+
+  static_assert(is_equal(SLF::test_function_filename_indirect(),
+                         SLF::global_info_filename), "");
+  static_assert(is_equal(SLF::test_function_filename_template_indirect(42),
+                         SLF::global_info_filename), "");
+
+  static_assert(test_file_name_simple() != nullptr);
+  static_assert(is_equal(test_file_name_simple(), "source_location.cpp"));
+}
+
+void test_class() {
+#line 315
+  using SLF::TestClass;
+  constexpr TestClass Default;
+  constexpr TestClass InParam{42};
+  constexpr TestClass Template{42, 42};
+  constexpr auto *F = Default.info_file_name;
+  constexpr auto Char = F[0];
+  static_assert(is_equal(Default.info_file_name, SLF::FILE_NAME), "");
+  static_assert(is_equal(InParam.info_file_name, SLF::FILE_NAME), "");
+  static_assert(is_equal(InParam.ctor_info_file_name, __FILE_NAME__), "");
+}
+
+void test_aggr_class() {
+  using Agg = SLF::AggrClass<>;
+  constexpr Agg Default{};
+  constexpr Agg InitOne{42};
+  static_assert(is_equal(Default.init_info_file_name, __FILE_NAME__), "");
+  static_assert(is_equal(InitOne.init_info_file_name, __FILE_NAME__), "");
+}
+
+} // namespace test_file_name
+
 //===----------------------------------------------------------------------===//
 //                            __builtin_FUNCTION()
 //===----------------------------------------------------------------------===//
@@ -487,6 +537,7 @@
 #line 44 "test_file.c"
 static_assert(is_equal("test_file.c", __FILE__));
 static_assert(is_equal("test_file.c", __builtin_FILE()));
+static_assert(is_equal("test_file.c", __builtin_FILE_NAME()));
 static_assert(is_equal("test_file.c", SL::current().file()));
 static_assert(is_equal("test_file.c", SLF::test_function().file()));
 static_assert(is_equal(SLF::FILE, SLF::test_function_indirect().file()));
Index: clang/unittests/AST/ASTImporterTest.cpp
===================================================================
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -259,6 +259,10 @@
              Lang_CXX03, Verifier,
              functionDecl(hasDescendant(
                  sourceLocExpr(hasBuiltinStr("__builtin_FILE")))));
+  testImport("void declToImport() { (void)__builtin_FILE_NAME(); }", Lang_CXX03,
+             "", Lang_CXX03, Verifier,
+             functionDecl(hasDescendant(
+                 sourceLocExpr(hasBuiltinStr("__builtin_FILE_NAME")))));
   testImport("void declToImport() { (void)__builtin_COLUMN(); }", Lang_CXX03,
              "", Lang_CXX03, Verifier,
              functionDecl(hasDescendant(