RIscRIpt created this revision.
Herald added subscribers: PiotrZSL, carlosgalvezp, martong.
Herald added a reviewer: shafik.
Herald added a reviewer: njames93.
Herald added a project: All.
RIscRIpt requested review of this revision.
Herald added projects: clang, clang-tools-extra.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D157747

Files:
  clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp
  clang/include/clang/AST/Expr.h
  clang/include/clang/AST/Stmt.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/ASTImporter.cpp
  clang/lib/AST/Expr.cpp
  clang/lib/AST/JSONNodeDumper.cpp
  clang/lib/AST/StmtPrinter.cpp
  clang/lib/AST/TextNodeDumper.cpp
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/Lex/LiteralSupport.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/TreeTransform.h
  clang/test/AST/Interp/literals.cpp
  clang/test/Sema/ms_predefined_expr.cpp

Index: clang/test/Sema/ms_predefined_expr.cpp
===================================================================
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -1,16 +1,31 @@
-// RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
+// RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions -std=c++20
 
 using size_t = __SIZE_TYPE__;
 
 // Test array initialization
 void array_init() {
- const char a[] = __FUNCTION__; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
- const char b[] = __FUNCDNAME__; // expected-warning{{initializing an array from a '__FUNCDNAME__' predefined identifier is a Microsoft extension}}
- const char c[] = __FUNCSIG__; // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
- const char d[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
- const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
- const wchar_t f[] = L__FUNCTION__; // expected-warning{{initializing an array from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
- const wchar_t g[] = L__FUNCSIG__; // expected-warning{{initializing an array from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}
+ const char a_f[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
+ const char a_P[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
+
+ const char a_F[] = __FUNCTION__;  // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const char a_D[] = __FUNCDNAME__; // expected-warning{{initializing an array from a '__FUNCDNAME__' predefined identifier is a Microsoft extension}}
+ const char a_S[] = __FUNCSIG__;   // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
+
+ const wchar_t L_F[] = L__FUNCTION__;  // expected-warning{{initializing an array from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t L_D[] = L__FUNCDNAME__; // expected-warning{{initializing an array from a 'L__FUNCDNAME__' predefined identifier is a Microsoft extension}}
+ const wchar_t L_S[] = L__FUNCSIG__;   // expected-warning{{initializing an array from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}
+
+ const char8_t u8_F[] = u8__FUNCTION__;  // expected-warning{{initializing an array from a 'u8__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const char8_t u8_D[] = u8__FUNCDNAME__; // expected-warning{{initializing an array from a 'u8__FUNCDNAME__' predefined identifier is a Microsoft extension}}
+ const char8_t u8_S[] = u8__FUNCSIG__;   // expected-warning{{initializing an array from a 'u8__FUNCSIG__' predefined identifier is a Microsoft extension}}
+
+ const char16_t u_F[] = u__FUNCTION__;  // expected-warning{{initializing an array from a 'u__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const char16_t u_D[] = u__FUNCDNAME__; // expected-warning{{initializing an array from a 'u__FUNCDNAME__' predefined identifier is a Microsoft extension}}
+ const char16_t u_S[] = u__FUNCSIG__;   // expected-warning{{initializing an array from a 'u__FUNCSIG__' predefined identifier is a Microsoft extension}}
+
+ const char32_t U_F[] = U__FUNCTION__;  // expected-warning{{initializing an array from a 'U__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const char32_t U_D[] = U__FUNCDNAME__; // expected-warning{{initializing an array from a 'U__FUNCDNAME__' predefined identifier is a Microsoft extension}}
+ const char32_t U_S[] = U__FUNCSIG__;   // expected-warning{{initializing an array from a 'U__FUNCSIG__' predefined identifier is a Microsoft extension}}
 }
 
 // Test function local identifiers outside of a function
@@ -100,24 +115,31 @@
 
 extern "C" void test_wide_concat() {
   // test L"" + ""
-  ASSERT_EQ(L"" __FUNCTION__, L__FUNCTION__); // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
-  ASSERT_EQ(L"" __FUNCSIG__, L__FUNCSIG__);   // expected-warning{{expansion of predefined identifier '__FUNCSIG__' to a string literal is a Microsoft extension}}
+  ASSERT_EQ(L"" __FUNCTION__, L__FUNCTION__);   // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  ASSERT_EQ(L"" __FUNCDNAME__, L__FUNCDNAME__); // expected-warning{{expansion of predefined identifier '__FUNCDNAME__' to a string literal is a Microsoft extension}}
+  ASSERT_EQ(L"" __FUNCSIG__, L__FUNCSIG__);     // expected-warning{{expansion of predefined identifier '__FUNCSIG__' to a string literal is a Microsoft extension}}
 
   // test Lx + ""
-  ASSERT_EQ(L__FUNCTION__, L__FUNCTION__ ""); // expected-warning{{expansion of predefined identifier 'L__FUNCTION__' to a string literal is a Microsoft extension}}
-  ASSERT_EQ(L__FUNCSIG__, L__FUNCSIG__ "");   // expected-warning{{expansion of predefined identifier 'L__FUNCSIG__' to a string literal is a Microsoft extension}}
+  ASSERT_EQ(L__FUNCTION__, L__FUNCTION__ "");   // expected-warning{{expansion of predefined identifier 'L__FUNCTION__' to a string literal is a Microsoft extension}}
+  ASSERT_EQ(L__FUNCDNAME__, L__FUNCDNAME__ ""); // expected-warning{{expansion of predefined identifier 'L__FUNCDNAME__' to a string literal is a Microsoft extension}}
+  ASSERT_EQ(L__FUNCSIG__, L__FUNCSIG__ "");     // expected-warning{{expansion of predefined identifier 'L__FUNCSIG__' to a string literal is a Microsoft extension}}
 
   ASSERT_EQ(L"left_" L__FUNCTION__, L"left_test_wide_concat");                   // expected-warning{{expansion of predefined identifier 'L__FUNCTION__' to a string literal is a Microsoft extension}}
+  ASSERT_EQ(L"left_" L__FUNCDNAME__, L"left_test_wide_concat");                  // expected-warning{{expansion of predefined identifier 'L__FUNCDNAME__' to a string literal is a Microsoft extension}}
   ASSERT_EQ(L"left " L__FUNCSIG__, L"left void __cdecl test_wide_concat(void)"); // expected-warning{{expansion of predefined identifier 'L__FUNCSIG__' to a string literal is a Microsoft extension}}
 
   ASSERT_EQ(L__FUNCTION__ L"_right", L"test_wide_concat_right");                   // expected-warning{{expansion of predefined identifier 'L__FUNCTION__' to a string literal is a Microsoft extension}}
+  ASSERT_EQ(L__FUNCDNAME__ L"_right", L"test_wide_concat_right");                  // expected-warning{{expansion of predefined identifier 'L__FUNCDNAME__' to a string literal is a Microsoft extension}}
   ASSERT_EQ(L__FUNCSIG__ L" right", L"void __cdecl test_wide_concat(void) right"); // expected-warning{{expansion of predefined identifier 'L__FUNCSIG__' to a string literal is a Microsoft extension}}
 
   ASSERT_EQ(L"left_" L__FUNCTION__ L"_right", L"left_test_wide_concat_right");                   // expected-warning{{expansion of predefined identifier 'L__FUNCTION__' to a string literal is a Microsoft extension}}
+  ASSERT_EQ(L"left_" L__FUNCDNAME__ L"_right", L"left_test_wide_concat_right");                  // expected-warning{{expansion of predefined identifier 'L__FUNCDNAME__' to a string literal is a Microsoft extension}}
   ASSERT_EQ(L"left " L__FUNCSIG__ L" right", L"left void __cdecl test_wide_concat(void) right"); // expected-warning{{expansion of predefined identifier 'L__FUNCSIG__' to a string literal is a Microsoft extension}}
 
-  ASSERT_EQ(L__FUNCTION__ L"/" L__FUNCSIG__, L"test_wide_concat/void __cdecl test_wide_concat(void)"); // expected-warning{{expansion of predefined identifier 'L__FUNCTION__' to a string literal is a Microsoft extension}} \
-                                                                                                       // expected-warning{{expansion of predefined identifier 'L__FUNCSIG__' to a string literal is a Microsoft extension}}
+  ASSERT_EQ(L__FUNCTION__ L"/" L__FUNCSIG__ L"/" L__FUNCDNAME__, L"test_wide_concat/void __cdecl test_wide_concat(void)/test_wide_concat"); // \
+      // expected-warning{{expansion of predefined identifier 'L__FUNCTION__' to a string literal is a Microsoft extension}} \
+      // expected-warning{{expansion of predefined identifier 'L__FUNCDNAME__' to a string literal is a Microsoft extension}} \
+      // expected-warning{{expansion of predefined identifier 'L__FUNCSIG__' to a string literal is a Microsoft extension}}
 }
 
 void test_encoding() {
Index: clang/test/AST/Interp/literals.cpp
===================================================================
--- clang/test/AST/Interp/literals.cpp
+++ clang/test/AST/Interp/literals.cpp
@@ -991,11 +991,10 @@
   }
 
   void foo() {
-    static_assert(strings_match(__FUNCSIG__, "void __cdecl PredefinedExprs::foo(void)"), "");
-    static_assert(strings_match(L__FUNCSIG__, L"void __cdecl PredefinedExprs::foo(void)"), "");
-    static_assert(strings_match(L__FUNCTION__, L"foo"), "");
-    static_assert(strings_match(__FUNCTION__, "foo"), "");
     static_assert(strings_match(__func__, "foo"), "");
+    static_assert(strings_match(__FUNCTION__, "foo"), "");
+    static_assert(strings_match(__FUNCDNAME__, "_ZN15PredefinedExprs3fooEv"), "");
+    static_assert(strings_match(__FUNCSIG__, "void __cdecl PredefinedExprs::foo(void)"), "");
     static_assert(strings_match(__PRETTY_FUNCTION__, "void PredefinedExprs::foo()"), "");
   }
 
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -2617,8 +2617,9 @@
   /// By default, performs semantic analysis to build the new expression.
   /// Subclasses may override this routine to provide different behavior.
   ExprResult RebuildPredefinedExpr(SourceLocation Loc,
-                                   PredefinedExpr::IdentKind IK) {
-    return getSema().BuildPredefinedExpr(Loc, IK);
+                                   PredefinedExpr::IdentKind IK,
+                                   StringLiteral::StringKind E) {
+    return getSema().BuildPredefinedExpr(Loc, IK, E);
   }
 
   /// Build a new expression that references a declaration.
@@ -10813,8 +10814,8 @@
   if (!E->isTypeDependent())
     return E;
 
-  return getDerived().RebuildPredefinedExpr(E->getLocation(),
-                                            E->getIdentKind());
+  return getDerived().RebuildPredefinedExpr(E->getLocation(), E->getIdentKind(),
+                                            E->getEncoding());
 }
 
 template<typename Derived>
Index: clang/lib/Sema/SemaTemplateInstantiate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1772,7 +1772,8 @@
   if (!E->isTypeDependent())
     return E;
 
-  return getSema().BuildPredefinedExpr(E->getLocation(), E->getIdentKind());
+  return getSema().BuildPredefinedExpr(E->getLocation(), E->getIdentKind(),
+                                       E->getEncoding());
 }
 
 ExprResult
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -1883,24 +1883,45 @@
       ContainsUnexpandedParameterPack, ResultIndex);
 }
 
-static PredefinedExpr::IdentKind getPredefinedExprKind(tok::TokenKind Kind) {
+static std::pair<PredefinedExpr::IdentKind, StringLiteral::StringKind>
+getPredefinedExprKind(tok::TokenKind Kind) {
   switch (Kind) {
   default:
     llvm_unreachable("unexpected TokenKind");
   case tok::kw___func__:
-    return PredefinedExpr::Func; // [C99 6.4.2.2]
+    return {PredefinedExpr::Func, StringLiteral::Ordinary}; // [C99 6.4.2.2]
   case tok::kw___FUNCTION__:
-    return PredefinedExpr::Function;
+    return {PredefinedExpr::Function, StringLiteral::Ordinary};
   case tok::kw___FUNCDNAME__:
-    return PredefinedExpr::FuncDName; // [MS]
+    return {PredefinedExpr::FuncDName, StringLiteral::Ordinary}; // [MS]
   case tok::kw___FUNCSIG__:
-    return PredefinedExpr::FuncSig; // [MS]
+    return {PredefinedExpr::FuncSig, StringLiteral::Ordinary}; // [MS]
   case tok::kw_L__FUNCTION__:
-    return PredefinedExpr::LFunction; // [MS]
+    return {PredefinedExpr::Function, StringLiteral::Wide}; // [MS]
+  case tok::kw_L__FUNCDNAME__:
+    return {PredefinedExpr::FuncDName, StringLiteral::Wide}; // [MS]
   case tok::kw_L__FUNCSIG__:
-    return PredefinedExpr::LFuncSig; // [MS]
+    return {PredefinedExpr::FuncSig, StringLiteral::Wide}; // [MS]
+  case tok::kw_u8__FUNCTION__:
+    return {PredefinedExpr::Function, StringLiteral::UTF8}; // [MS]
+  case tok::kw_u8__FUNCDNAME__:
+    return {PredefinedExpr::FuncDName, StringLiteral::UTF8}; // [MS]
+  case tok::kw_u8__FUNCSIG__:
+    return {PredefinedExpr::FuncSig, StringLiteral::UTF8}; // [MS]
+  case tok::kw_u__FUNCTION__:
+    return {PredefinedExpr::Function, StringLiteral::UTF16}; // [MS]
+  case tok::kw_u__FUNCDNAME__:
+    return {PredefinedExpr::FuncDName, StringLiteral::UTF16}; // [MS]
+  case tok::kw_u__FUNCSIG__:
+    return {PredefinedExpr::FuncSig, StringLiteral::UTF16}; // [MS]
+  case tok::kw_U__FUNCTION__:
+    return {PredefinedExpr::Function, StringLiteral::UTF32}; // [MS]
+  case tok::kw_U__FUNCDNAME__:
+    return {PredefinedExpr::FuncDName, StringLiteral::UTF32}; // [MS]
+  case tok::kw_U__FUNCSIG__:
+    return {PredefinedExpr::FuncSig, StringLiteral::UTF32}; // [MS]
   case tok::kw___PRETTY_FUNCTION__:
-    return PredefinedExpr::PrettyFunction; // [GNU]
+    return {PredefinedExpr::PrettyFunction, StringLiteral::Ordinary}; // [GNU]
   }
 }
 
@@ -2001,20 +2022,36 @@
     // Stringify predefined expression
     Diag(Tok.getLocation(), diag::ext_string_literal_from_predefined)
         << Tok.getKind();
+    auto [ExprKind, Encoding] = getPredefinedExprKind(Tok.getKind());
     SmallString<64> Str;
     llvm::raw_svector_ostream OS(Str);
     Token &Exp = ExpandedToks.emplace_back();
     Exp.startToken();
-    if (Tok.getKind() == tok::kw_L__FUNCTION__ ||
-        Tok.getKind() == tok::kw_L__FUNCSIG__) {
+    switch (Encoding) {
+    case StringLiteral::Ordinary:
+      Exp.setKind(tok::string_literal);
+      break;
+    case StringLiteral::Wide:
       OS << 'L';
       Exp.setKind(tok::wide_string_literal);
-    } else {
-      Exp.setKind(tok::string_literal);
+      break;
+    case StringLiteral::UTF8:
+      OS << "u8";
+      Exp.setKind(tok::utf8_string_literal);
+      break;
+    case StringLiteral::UTF16:
+      OS << 'u';
+      Exp.setKind(tok::utf16_string_literal);
+      break;
+    case StringLiteral::UTF32:
+      OS << 'U';
+      Exp.setKind(tok::utf32_string_literal);
+      break;
+    case StringLiteral::Unevaluated:
+      llvm_unreachable("unexpected encoding");
     }
     OS << '"'
-       << Lexer::Stringify(PredefinedExpr::ComputeName(
-              getPredefinedExprKind(Tok.getKind()), CurrentDecl))
+       << Lexer::Stringify(PredefinedExpr::ComputeName(ExprKind, CurrentDecl))
        << '"';
     PP.CreateString(OS.str(), Exp, Tok.getLocation(), Tok.getEndLoc());
   }
@@ -3692,7 +3729,7 @@
 }
 
 static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source,
-                                    SmallString<32> &Target) {
+                                    SmallVectorImpl<char> &Target) {
   Target.resize(CharByteWidth * (Source.size() + 1));
   char *ResultPtr = &Target[0];
   const llvm::UTF8 *ErrorPtr;
@@ -3704,7 +3741,8 @@
 }
 
 ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
-                                     PredefinedExpr::IdentKind IK) {
+                                     PredefinedExpr::IdentKind IK,
+                                     StringLiteral::StringKind E) {
   Decl *currentDecl = getCurLocalScopeDecl();
   if (!currentDecl) {
     Diag(Loc, diag::ext_predef_outside_function);
@@ -3716,35 +3754,43 @@
   if (cast<DeclContext>(currentDecl)->isDependentContext())
     ResTy = Context.DependentTy;
   else {
-    // Pre-defined identifiers are of type char[x], where x is the length of
-    // the string.
+    // Pre-defined identifiers are of type CharT[x],
+    // where x is the length of the string.
+    SmallString<128> RawChars;
     auto Str = PredefinedExpr::ComputeName(IK, currentDecl);
-    unsigned Length = Str.length();
-
-    llvm::APInt LengthI(32, Length + 1);
-    if (IK == PredefinedExpr::LFunction || IK == PredefinedExpr::LFuncSig) {
-      ResTy =
-          Context.adjustStringLiteralBaseType(Context.WideCharTy.withConst());
-      SmallString<32> RawChars;
-      ConvertUTF8ToWideString(Context.getTypeSizeInChars(ResTy).getQuantity(),
-                              Str, RawChars);
-      ResTy = Context.getConstantArrayType(ResTy, LengthI, nullptr,
-                                           ArrayType::Normal,
-                                           /*IndexTypeQuals*/ 0);
-      SL = StringLiteral::Create(Context, RawChars, StringLiteral::Wide,
-                                 /*Pascal*/ false, ResTy, Loc);
-    } else {
-      ResTy = Context.adjustStringLiteralBaseType(Context.CharTy.withConst());
-      ResTy = Context.getConstantArrayType(ResTy, LengthI, nullptr,
-                                           ArrayType::Normal,
-                                           /*IndexTypeQuals*/ 0);
-      SL = StringLiteral::Create(Context, Str, StringLiteral::Ordinary,
-                                 /*Pascal*/ false, ResTy, Loc);
+    llvm::APInt LengthI(32, Str.length() + 1);
+
+    switch (E) {
+    case StringLiteral::Ordinary:
+      ResTy = Context.CharTy;
+      break;
+    case StringLiteral::Wide:
+      ResTy = Context.WideCharTy;
+      break;
+    case StringLiteral::UTF8:
+      ResTy = Context.Char8Ty;
+      break;
+    case StringLiteral::UTF16:
+      ResTy = Context.Char16Ty;
+      break;
+    case StringLiteral::UTF32:
+      ResTy = Context.Char32Ty;
+      break;
+    default:
+      llvm_unreachable("unexpected PredefinedExpr encoding");
     }
+
+    ResTy = Context.adjustStringLiteralBaseType(ResTy.withConst());
+    ConvertUTF8ToWideString(Context.getTypeSizeInChars(ResTy).getQuantity(),
+                            Str, RawChars);
+    ResTy = Context.getConstantArrayType(
+        ResTy, LengthI, nullptr, ArrayType::Normal, /*IndexTypeQuals*/ 0);
+    SL = StringLiteral::Create(Context, RawChars, E, /*Pascal*/ false, ResTy,
+                               Loc);
   }
 
-  return PredefinedExpr::Create(Context, Loc, ResTy, IK, LangOpts.MicrosoftExt,
-                                SL);
+  return PredefinedExpr::Create(Context, Loc, ResTy, IK, E,
+                                LangOpts.MicrosoftExt, SL);
 }
 
 ExprResult Sema::BuildSYCLUniqueStableNameExpr(SourceLocation OpLoc,
@@ -3770,7 +3816,8 @@
 }
 
 ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
-  return BuildPredefinedExpr(Loc, getPredefinedExprKind(Kind));
+  auto [ExprKind, Encoding] = getPredefinedExprKind(Kind);
+  return BuildPredefinedExpr(Loc, ExprKind, Encoding);
 }
 
 ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) {
Index: clang/lib/Parse/ParseExpr.cpp
===================================================================
--- clang/lib/Parse/ParseExpr.cpp
+++ clang/lib/Parse/ParseExpr.cpp
@@ -1296,7 +1296,17 @@
   case tok::kw___FUNCDNAME__:   // primary-expression: __FUNCDNAME__ [MS]
   case tok::kw___FUNCSIG__:     // primary-expression: __FUNCSIG__ [MS]
   case tok::kw_L__FUNCTION__:   // primary-expression: L__FUNCTION__ [MS]
+  case tok::kw_L__FUNCDNAME__:  // primary-expression: L__FUNCDNAME__ [MS]
   case tok::kw_L__FUNCSIG__:    // primary-expression: L__FUNCSIG__ [MS]
+  case tok::kw_u8__FUNCTION__:  // primary-expression: u8__FUNCTION__ [MS]
+  case tok::kw_u8__FUNCDNAME__: // primary-expression: u8__FUNCDNAME__ [MS]
+  case tok::kw_u8__FUNCSIG__:   // primary-expression: u8__FUNCSIG__ [MS]
+  case tok::kw_u__FUNCTION__:   // primary-expression: u__FUNCTION__ [MS]
+  case tok::kw_u__FUNCDNAME__:  // primary-expression: u__FUNCDNAME__ [MS]
+  case tok::kw_u__FUNCSIG__:    // primary-expression: u__FUNCSIG__ [MS]
+  case tok::kw_U__FUNCTION__:   // primary-expression: U__FUNCTION__ [MS]
+  case tok::kw_U__FUNCDNAME__:  // primary-expression: U__FUNCDNAME__ [MS]
+  case tok::kw_U__FUNCSIG__:    // primary-expression: U__FUNCSIG__ [MS]
   case tok::kw___PRETTY_FUNCTION__:  // primary-expression: __P..Y_F..N__ [GNU]
     // Function local predefined macros are represented by PredefinedExpr except
     // when Microsoft extensions are enabled and one of these macros is adjacent
Index: clang/lib/Lex/LiteralSupport.cpp
===================================================================
--- clang/lib/Lex/LiteralSupport.cpp
+++ clang/lib/Lex/LiteralSupport.cpp
@@ -442,9 +442,14 @@
 bool clang::isFunctionLocalStringLiteralMacro(tok::TokenKind K,
                                               const LangOptions &LO) {
   return LO.MicrosoftExt &&
-         (K == tok::kw___FUNCTION__ || K == tok::kw_L__FUNCTION__ ||
-          K == tok::kw___FUNCSIG__ || K == tok::kw_L__FUNCSIG__ ||
-          K == tok::kw___FUNCDNAME__);
+         (K == tok::kw___FUNCTION__ || K == tok::kw___FUNCDNAME__ ||
+          K == tok::kw___FUNCSIG__ || K == tok::kw_L__FUNCTION__ ||
+          K == tok::kw_L__FUNCDNAME__ || K == tok::kw_L__FUNCSIG__ ||
+          K == tok::kw_u8__FUNCTION__ || K == tok::kw_u8__FUNCDNAME__ ||
+          K == tok::kw_u8__FUNCSIG__ || K == tok::kw_u__FUNCTION__ ||
+          K == tok::kw_u__FUNCDNAME__ || K == tok::kw_u__FUNCSIG__ ||
+          K == tok::kw_U__FUNCTION__ || K == tok::kw_U__FUNCDNAME__ ||
+          K == tok::kw_U__FUNCSIG__);
 }
 
 bool clang::tokenIsLikeStringLiteral(const Token &Tok, const LangOptions &LO) {
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -3020,8 +3020,7 @@
   StringRef FnName = CurFn->getName();
   if (FnName.startswith("\01"))
     FnName = FnName.substr(1);
-  StringRef NameItems[] = {
-      PredefinedExpr::getIdentKindName(E->getIdentKind()), FnName};
+  StringRef NameItems[] = {E->getIdentKindName(), FnName};
   std::string GVName = llvm::join(NameItems, NameItems + 2, ".");
   if (auto *BD = dyn_cast_or_null<BlockDecl>(CurCodeDecl)) {
     std::string Name = std::string(SL->getString());
Index: clang/lib/AST/TextNodeDumper.cpp
===================================================================
--- clang/lib/AST/TextNodeDumper.cpp
+++ clang/lib/AST/TextNodeDumper.cpp
@@ -1084,7 +1084,7 @@
 }
 
 void TextNodeDumper::VisitPredefinedExpr(const PredefinedExpr *Node) {
-  OS << " " << PredefinedExpr::getIdentKindName(Node->getIdentKind());
+  OS << " " << Node->getIdentKindName();
 }
 
 void TextNodeDumper::VisitCharacterLiteral(const CharacterLiteral *Node) {
Index: clang/lib/AST/StmtPrinter.cpp
===================================================================
--- clang/lib/AST/StmtPrinter.cpp
+++ clang/lib/AST/StmtPrinter.cpp
@@ -1247,7 +1247,7 @@
 }
 
 void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
-  OS << PredefinedExpr::getIdentKindName(Node->getIdentKind());
+  OS << Node->getIdentKindName();
 }
 
 void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) {
Index: clang/lib/AST/JSONNodeDumper.cpp
===================================================================
--- clang/lib/AST/JSONNodeDumper.cpp
+++ clang/lib/AST/JSONNodeDumper.cpp
@@ -1261,7 +1261,7 @@
 }
 
 void JSONNodeDumper::VisitPredefinedExpr(const PredefinedExpr *PE) {
-  JOS.attribute("name", PredefinedExpr::getIdentKindName(PE->getIdentKind()));
+  JOS.attribute("name", PE->getIdentKindName());
 }
 
 void JSONNodeDumper::VisitUnaryOperator(const UnaryOperator *UO) {
Index: clang/lib/AST/Expr.cpp
===================================================================
--- clang/lib/AST/Expr.cpp
+++ clang/lib/AST/Expr.cpp
@@ -665,11 +665,15 @@
 }
 
 PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
-                               bool IsTransparent, StringLiteral *SL)
+                               StringLiteral::StringKind E, bool IsTransparent,
+                               StringLiteral *SL)
     : Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary) {
   PredefinedExprBits.Kind = IK;
   assert((getIdentKind() == IK) &&
          "IdentKind do not fit in PredefinedExprBitfields!");
+  PredefinedExprBits.Encoding = E;
+  assert((getEncoding() == E) &&
+         "Encoding do not fit in PredefinedExprBitfields!");
   bool HasFunctionName = SL != nullptr;
   PredefinedExprBits.HasFunctionName = HasFunctionName;
   PredefinedExprBits.IsTransparent = IsTransparent;
@@ -686,11 +690,12 @@
 
 PredefinedExpr *PredefinedExpr::Create(const ASTContext &Ctx, SourceLocation L,
                                        QualType FNTy, IdentKind IK,
+                                       StringLiteral::StringKind E,
                                        bool IsTransparent, StringLiteral *SL) {
   bool HasFunctionName = SL != nullptr;
   void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *>(HasFunctionName),
                            alignof(PredefinedExpr));
-  return new (Mem) PredefinedExpr(L, FNTy, IK, IsTransparent, SL);
+  return new (Mem) PredefinedExpr(L, FNTy, IK, E, IsTransparent, SL);
 }
 
 PredefinedExpr *PredefinedExpr::CreateEmpty(const ASTContext &Ctx,
@@ -700,22 +705,62 @@
   return new (Mem) PredefinedExpr(EmptyShell(), HasFunctionName);
 }
 
-StringRef PredefinedExpr::getIdentKindName(PredefinedExpr::IdentKind IK) {
+StringRef PredefinedExpr::getIdentKindName(PredefinedExpr::IdentKind IK,
+                                           StringLiteral::StringKind E) {
   switch (IK) {
   case Func:
     return "__func__";
+
   case Function:
-    return "__FUNCTION__";
+    switch (E) {
+    case StringLiteral::Ordinary:
+      return "__FUNCTION__";
+    case StringLiteral::Wide:
+      return "L__FUNCTION__";
+    case StringLiteral::UTF8:
+      return "u8__FUNCTION__";
+    case StringLiteral::UTF16:
+      return "u__FUNCTION__";
+    case StringLiteral::UTF32:
+      return "U__FUNCTION__";
+    case StringLiteral::Unevaluated:
+      llvm_unreachable("unexpected PredefinedExpr encoding");
+    }
+
   case FuncDName:
-    return "__FUNCDNAME__";
-  case LFunction:
-    return "L__FUNCTION__";
+    switch (E) {
+    case StringLiteral::Ordinary:
+      return "__FUNCDNAME__";
+    case StringLiteral::Wide:
+      return "L__FUNCDNAME__";
+    case StringLiteral::UTF8:
+      return "u8__FUNCDNAME__";
+    case StringLiteral::UTF16:
+      return "u__FUNCDNAME__";
+    case StringLiteral::UTF32:
+      return "U__FUNCDNAME__";
+    case StringLiteral::Unevaluated:
+      llvm_unreachable("unexpected PredefinedExpr encoding");
+    }
+
+  case FuncSig:
+    switch (E) {
+    case StringLiteral::Ordinary:
+      return "__FUNCSIG__";
+    case StringLiteral::Wide:
+      return "L__FUNCSIG__";
+    case StringLiteral::UTF8:
+      return "u8__FUNCSIG__";
+    case StringLiteral::UTF16:
+      return "u__FUNCSIG__";
+    case StringLiteral::UTF32:
+      return "U__FUNCSIG__";
+    case StringLiteral::Unevaluated:
+      llvm_unreachable("unexpected PredefinedExpr encoding");
+    }
+
   case PrettyFunction:
     return "__PRETTY_FUNCTION__";
-  case FuncSig:
-    return "__FUNCSIG__";
-  case LFuncSig:
-    return "L__FUNCSIG__";
   case PrettyFunctionNoVirtual:
     break;
   }
@@ -772,8 +817,7 @@
     return std::string(Out.str());
   }
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
-    if (IK != PrettyFunction && IK != PrettyFunctionNoVirtual &&
-        IK != FuncSig && IK != LFuncSig)
+    if (IK != PrettyFunction && IK != PrettyFunctionNoVirtual && IK != FuncSig)
       return FD->getNameAsString();
 
     SmallString<256> Name;
@@ -812,7 +856,7 @@
     if (FD->hasWrittenPrototype())
       FT = dyn_cast<FunctionProtoType>(AFT);
 
-    if (IK == FuncSig || IK == LFuncSig) {
+    if (IK == FuncSig) {
       switch (AFT->getCallConv()) {
       case CC_C: POut << "__cdecl "; break;
       case CC_X86StdCall: POut << "__stdcall "; break;
@@ -837,8 +881,7 @@
       if (FT->isVariadic()) {
         if (FD->getNumParams()) POut << ", ";
         POut << "...";
-      } else if ((IK == FuncSig || IK == LFuncSig ||
-                  !Context.getLangOpts().CPlusPlus) &&
+      } else if ((IK == FuncSig || !Context.getLangOpts().CPlusPlus) &&
                  !Decl->getNumParams()) {
         POut << "void";
       }
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -7160,8 +7160,8 @@
     return std::move(Err);
 
   return PredefinedExpr::Create(Importer.getToContext(), ToBeginLoc, ToType,
-                                E->getIdentKind(), E->isTransparent(),
-                                ToFunctionName);
+                                E->getIdentKind(), E->getEncoding(),
+                                E->isTransparent(), ToFunctionName);
 }
 
 ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -5718,7 +5718,8 @@
   std::vector<Token> ExpandFunctionLocalPredefinedMacros(ArrayRef<Token> Toks);
 
   ExprResult BuildPredefinedExpr(SourceLocation Loc,
-                                 PredefinedExpr::IdentKind IK);
+                                 PredefinedExpr::IdentKind IK,
+                                 StringLiteral::StringKind E);
   ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
   ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val);
 
Index: clang/include/clang/Basic/TokenKinds.def
===================================================================
--- clang/include/clang/Basic/TokenKinds.def
+++ clang/include/clang/Basic/TokenKinds.def
@@ -466,7 +466,17 @@
 KEYWORD(__FUNCDNAME__               , KEYMS)
 KEYWORD(__FUNCSIG__                 , KEYMS)
 KEYWORD(L__FUNCTION__               , KEYMS)
+KEYWORD(L__FUNCDNAME__              , KEYMS)
 KEYWORD(L__FUNCSIG__                , KEYMS)
+KEYWORD(u8__FUNCTION__              , KEYMS)
+KEYWORD(u8__FUNCDNAME__             , KEYMS)
+KEYWORD(u8__FUNCSIG__               , KEYMS)
+KEYWORD(u__FUNCTION__               , KEYMS)
+KEYWORD(u__FUNCDNAME__              , KEYMS)
+KEYWORD(u__FUNCSIG__                , KEYMS)
+KEYWORD(U__FUNCTION__               , KEYMS)
+KEYWORD(U__FUNCDNAME__              , KEYMS)
+KEYWORD(U__FUNCSIG__                , KEYMS)
 TYPE_TRAIT_1(__is_interface_class, IsInterfaceClass, KEYMS)
 TYPE_TRAIT_1(__is_sealed, IsSealed, KEYMS)
 
Index: clang/include/clang/AST/Stmt.h
===================================================================
--- clang/include/clang/AST/Stmt.h
+++ clang/include/clang/AST/Stmt.h
@@ -358,7 +358,11 @@
 
     /// The kind of this PredefinedExpr. One of the enumeration values
     /// in PredefinedExpr::IdentKind.
-    unsigned Kind : 4;
+    unsigned Kind : 3;
+
+    /// The encoding of this predefined expression.
+    /// One of the enumeration values of StringLiteral::StringKind.
+    unsigned Encoding : 3;
 
     /// True if this PredefinedExpr has a trailing "StringLiteral *"
     /// for the predefined identifier.
Index: clang/include/clang/AST/Expr.h
===================================================================
--- clang/include/clang/AST/Expr.h
+++ clang/include/clang/AST/Expr.h
@@ -1994,10 +1994,8 @@
   enum IdentKind {
     Func,
     Function,
-    LFunction, // Same as Function, but as wide string.
     FuncDName,
     FuncSig,
-    LFuncSig, // Same as FuncSig, but as wide string
     PrettyFunction,
     /// The same as PrettyFunction, except that the
     /// 'virtual' keyword is omitted for virtual member functions.
@@ -2006,7 +2004,8 @@
 
 private:
   PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
-                 bool IsTransparent, StringLiteral *SL);
+                 StringLiteral::StringKind E, bool IsTransparent,
+                 StringLiteral *SL);
 
   explicit PredefinedExpr(EmptyShell Empty, bool HasFunctionName);
 
@@ -2025,7 +2024,8 @@
   /// If IsTransparent, the PredefinedExpr is transparently handled as a
   /// StringLiteral.
   static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L,
-                                QualType FNTy, IdentKind IK, bool IsTransparent,
+                                QualType FNTy, IdentKind IK,
+                                StringLiteral::StringKind E, bool IsTransparent,
                                 StringLiteral *SL);
 
   /// Create an empty PredefinedExpr.
@@ -2036,6 +2036,10 @@
     return static_cast<IdentKind>(PredefinedExprBits.Kind);
   }
 
+  StringLiteral::StringKind getEncoding() const {
+    return static_cast<StringLiteral::StringKind>(PredefinedExprBits.Encoding);
+  }
+
   bool isTransparent() const { return PredefinedExprBits.IsTransparent; }
 
   SourceLocation getLocation() const { return PredefinedExprBits.Loc; }
@@ -2053,9 +2057,10 @@
                : nullptr;
   }
 
-  static StringRef getIdentKindName(IdentKind IK);
+  static StringRef getIdentKindName(IdentKind IK,
+                                    StringLiteral::StringKind Encoding);
   StringRef getIdentKindName() const {
-    return getIdentKindName(getIdentKind());
+    return getIdentKindName(getIdentKind(), getEncoding());
   }
 
   static std::string ComputeName(IdentKind IK, const Decl *CurrentDecl);
Index: clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp
@@ -88,7 +88,7 @@
        "inside a lambda, '%0' expands to the name of the function call "
        "operator; consider capturing the name of the enclosing function "
        "explicitly")
-      << PredefinedExpr::getIdentKindName(E->getIdentKind());
+      << E->getIdentKindName();
 }
 
 } // namespace clang::tidy::bugprone
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to