[clang] [clang-cl] Fix value of __FUNCTION__ in MSVC mode. (PR #67592)

Zahira Ammarguellat via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 4 05:11:33 PDT 2023


https://github.com/zahiraam updated https://github.com/llvm/llvm-project/pull/67592

>From 55b67a58ef8b9856e5f0a8f535b8617f59711dec Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Wed, 27 Sep 2023 11:59:04 -0700
Subject: [PATCH 01/11] Fix value of __FUNCTION__ and __func__ in MSVC mode.

---
 clang/lib/AST/Expr.cpp                        |  9 ++-
 clang/lib/AST/TypePrinter.cpp                 | 21 +++++-
 clang/test/Analysis/eval-predefined-exprs.cpp |  4 +-
 .../CodeGenCXX/mangle-nttp-anon-union.cpp     |  2 +-
 clang/test/CodeGenCXX/predefined-expr.cpp     | 18 -----
 clang/test/SemaCXX/source_location.cpp        | 72 +++++++++++++++++++
 6 files changed, 99 insertions(+), 27 deletions(-)

diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index af82ca0784af413..49f3495c090f191 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -773,8 +773,8 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
   }
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
     const auto &LO = Context.getLangOpts();
-    if (((IK == Func || IK == Function) && !LO.MicrosoftExt) ||
-        (IK == LFunction && LO.MicrosoftExt))
+    if (((IK == Function || IK == Func) && !LO.MicrosoftExt) ||
+        ((IK == LFunction || IK == Func) && LO.MicrosoftExt))
       return FD->getNameAsString();
 
     SmallString<256> Name;
@@ -804,7 +804,10 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
     PrintingPolicy Policy(LO);
     PrettyCallbacks PrettyCB(LO);
     Policy.Callbacks = &PrettyCB;
-    Policy.UseClassForTemplateArgument = LO.MicrosoftExt;
+    if (IK == Function && LO.MicrosoftExt) {
+      Policy.UseClassForTemplateArgument = LO.MicrosoftExt;
+      Policy.MSVCFormatting = LO.MicrosoftExt;
+    }
     std::string Proto;
     llvm::raw_string_ostream POut(Proto);
 
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 3771a29f26b173f..8a7cf85cdf126b6 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -2195,6 +2195,7 @@ printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,
     llvm::SmallVector<TemplateArgument, 8> OrigArgs;
     for (const TA &A : Args)
       OrigArgs.push_back(getArgument(A));
+
     while (!Args.empty() && getArgument(Args.back()).getIsDefaulted())
       Args = Args.drop_back();
   }
@@ -2218,10 +2219,24 @@ printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,
     } else {
       if (!FirstArg)
         OS << Comma;
-      if (Policy.UseClassForTemplateArgument &&
-          Argument.getKind() == TemplateArgument::Type)
-        OS << "class ";
 
+      if (Policy.MSVCFormatting && Policy.UseClassForTemplateArgument &&
+          Argument.getKind() == TemplateArgument::Type &&
+          !Argument.getAsType()->isBuiltinType()) {
+        const Type *Ty = Argument.getAsType().getTypePtr();
+        const char *kw;
+        if (Ty->isStructureType())
+          kw = "struct ";
+        else if (Ty->isClassType())
+          kw = "class ";
+        else if (Ty->isUnionType())
+          kw = "union ";
+        else if (Ty->isEnumeralType())
+          kw = "enum ";
+        else
+          llvm_unreachable("argument type not expected");
+        OS << kw;
+      }
       // Tries to print the argument with location info if exists.
       printArgument(Arg, Policy, ArgOS,
                     TemplateParameterList::shouldIncludeTypeForArgument(
diff --git a/clang/test/Analysis/eval-predefined-exprs.cpp b/clang/test/Analysis/eval-predefined-exprs.cpp
index 7be441eb5bad943..a6bac5ee9d486d2 100644
--- a/clang/test/Analysis/eval-predefined-exprs.cpp
+++ b/clang/test/Analysis/eval-predefined-exprs.cpp
@@ -56,7 +56,7 @@ struct A {
     clang_analyzer_dump(__FUNCTION__);
     clang_analyzer_dump(__PRETTY_FUNCTION__);
 #ifdef ANALYZER_MS
-    // expected-warning at -4 {{&Element{"A::A",0 S64b,char}}}
+    // expected-warning at -4 {{&Element{"A",0 S64b,char}}}
     // expected-warning at -4 {{&Element{"A::A",0 S64b,char}}}
 #else
     // expected-warning at -7 {{&Element{"A",0 S64b,char}}}
@@ -80,7 +80,7 @@ struct A {
     clang_analyzer_dump(__FUNCTION__);
     clang_analyzer_dump(__PRETTY_FUNCTION__);
 #ifdef ANALYZER_MS
-    // expected-warning at -4 {{&Element{"A::~A",0 S64b,char}}}
+    // expected-warning at -4 {{&Element{"~A",0 S64b,char}}}
     // expected-warning at -4 {{&Element{"A::~A",0 S64b,char}}}
 #else
     // expected-warning at -7 {{&Element{"~A",0 S64b,char}}}
diff --git a/clang/test/CodeGenCXX/mangle-nttp-anon-union.cpp b/clang/test/CodeGenCXX/mangle-nttp-anon-union.cpp
index 78fa7c378c88d50..1982a3eeb941291 100644
--- a/clang/test/CodeGenCXX/mangle-nttp-anon-union.cpp
+++ b/clang/test/CodeGenCXX/mangle-nttp-anon-union.cpp
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -std=c++20 -emit-llvm %s -o - -triple=x86_64-linux-gnu | FileCheck %s
-// RUN: %clang_cc1 -std=c++20 -emit-llvm %s -o - -triple=x86_64-linux-gnu | llvm-cxxfilt -n | FileCheck %s --check-prefix DEMANGLED
+// RUN: %clang_cc1 -std=c++20 -emit-llvm %s -o - -triple=x86_64-linux-gnu | llvm-cxxfilt -n | FileCheck %s
 
 template<typename T>
 struct wrapper1 {
diff --git a/clang/test/CodeGenCXX/predefined-expr.cpp b/clang/test/CodeGenCXX/predefined-expr.cpp
index af76e0538a9ec9f..7f4863aa2066cf9 100644
--- a/clang/test/CodeGenCXX/predefined-expr.cpp
+++ b/clang/test/CodeGenCXX/predefined-expr.cpp
@@ -5,8 +5,6 @@
 // CHECK-DAG: private unnamed_addr constant [49 x i8] c"void functionTemplateExplicitSpecialization(int)\00"
 
 // CHECK-DAG: private unnamed_addr constant [95 x i8] c"void SpecializedClassTemplate<char>::memberFunctionTemplate(T, U) const [T = char, U = double]\00"
-// CHECK-DAG: private unnamed_addr constant [43 x i8] c"TestClass<class UnitTestNative>::TestClass\00"
-// CHECK-DAG: private unnamed_addr constant [10 x i8] c"TestClass\00"
 // CHECK-DAG: private unnamed_addr constant [85 x i8] c"void SpecializedClassTemplate<int>::memberFunctionTemplate(int, U) const [U = float]\00"
 // CHECK-DAG: private unnamed_addr constant [57 x i8] c"void NonTypeTemplateParam<42>::size() const [Count = 42]\00"
 // CHECK-DAG: private unnamed_addr constant [103 x i8] c"static void ClassWithTemplateTemplateParam<char>::staticMember() [T = char, Param = NS::ClassTemplate]\00"
@@ -458,21 +456,6 @@ class SpecializedClassTemplate<int>
   }
 };
 
-
-template <class T>
-class TestClass {
-public:
-   TestClass() {
-      const char* expected = "TestClass<class UnitTestNative>::TestClass";
-      if (strcmp(expected,__FUNCTION__)==0)
-        printf("PASSED\n");
-      else
-        printf("FAILED %s\n",__FUNCTION__);
-   }
-};
-
-class UnitTestNative {};
-
 int main() {
   ClassInAnonymousNamespace anonymousNamespace;
   anonymousNamespace.anonymousNamespaceFunction();
@@ -553,7 +536,6 @@ int main() {
   SpecializedClassTemplate<char> sct2;
   sct2.memberFunctionTemplate('0', 0.0);
 
-  TestClass<UnitTestNative> t;
   return 0;
 }
 
diff --git a/clang/test/SemaCXX/source_location.cpp b/clang/test/SemaCXX/source_location.cpp
index d4d4c8fa650e1af..043e67164cf1ef1 100644
--- a/clang/test/SemaCXX/source_location.cpp
+++ b/clang/test/SemaCXX/source_location.cpp
@@ -423,10 +423,17 @@ constexpr const char *test_func_simple(const char *__f = __builtin_FUNCTION()) {
 constexpr const char *get_function() {
   return __func__;
 }
+#ifdef MS
 constexpr bool test_function() {
+  return !is_equal(__func__, test_func_simple()) &&
+         !is_equal(get_function(), test_func_simple());
+}
+#else
+  constexpr bool test_function() {
   return is_equal(__func__, test_func_simple()) &&
          !is_equal(get_function(), test_func_simple());
 }
+#endif
 static_assert(test_function());
 
 template <class T, class U = SL>
@@ -463,8 +470,73 @@ void ctor_tests() {
 constexpr SL global_sl = SL::current();
 static_assert(is_equal(global_sl.function(), ""));
 
+template <class T>
+class TestBI {
+public:
+   TestBI() {
+#ifdef MS
+      static_assert(is_equal(__FUNCTION__, "test_func::TestBI<int>::TestBI"));
+      static_assert(is_equal(__func__, "TestBI"));
+#else
+      static_assert(is_equal(__func__, "TestBI"));
+      static_assert(is_equal(__func__, "TestBI"));
+#endif
+   }
+};
+
+template <class T>
+class TestClass {
+public:
+   TestClass() {
+#ifdef MS
+      static_assert(is_equal(__FUNCTION__, "test_func::TestClass<class test_func::C>::TestClass"));
+      static_assert(is_equal(__func__, "TestClass"));
+#else
+      static_assert(is_equal(__func__, "TestClass"));
+      static_assert(is_equal(__func__, "TestClass"));
+#endif
+   }
+};
+
+template <class T>
+class TestStruct {
+public:
+   TestStruct() {
+#ifdef MS
+      static_assert(is_equal(__FUNCTION__, "test_func::TestStruct<struct test_func::S>::TestStruct"));
+      static_assert(is_equal(__func__, "TestStruct"));
+#else
+      static_assert(is_equal(__func__, "TestStruct"));
+      static_assert(is_equal(__func__, "TestStruct"));
+#endif
+   }
+};
+
+template <class T>
+class TestEnum {
+public:
+   TestEnum() {
+#ifdef MS
+      static_assert(is_equal(__FUNCTION__, "test_func::TestEnum<enum test_func::E>::TestEnum"));
+      static_assert(is_equal(__func__, "TestEnum"));
+#else
+      static_assert(is_equal(__func__, "TestEnum"));
+      static_assert(is_equal(__func__, "TestEnum"));
+#endif
+   }
+};
+
+  class C {};
+struct S {};
+enum E {};
+
+test_func::TestBI<int> t1;
+test_func::TestClass<C> t2;
+test_func::TestStruct<S> t3;
+test_func::TestEnum<E> t4;
 } // namespace test_func
 
+
 //===----------------------------------------------------------------------===//
 //                            __builtin_FUNCSIG()
 //===----------------------------------------------------------------------===//

>From 3bb28808e98d37de55a7bf2a2bdc524f7219bb18 Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Wed, 27 Sep 2023 12:03:33 -0700
Subject: [PATCH 02/11] Fix format.

---
 clang/test/SemaCXX/source_location.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/SemaCXX/source_location.cpp b/clang/test/SemaCXX/source_location.cpp
index 043e67164cf1ef1..815eed121637ad4 100644
--- a/clang/test/SemaCXX/source_location.cpp
+++ b/clang/test/SemaCXX/source_location.cpp
@@ -526,7 +526,7 @@ class TestEnum {
    }
 };
 
-  class C {};
+class C {};
 struct S {};
 enum E {};
 

>From 3ea6fa5703e6f3d387c87d8c544fceea439f4ee7 Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Wed, 27 Sep 2023 12:38:50 -0700
Subject: [PATCH 03/11] Add undefined field.

---
 clang/include/clang/AST/PrettyPrinter.h | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index cee3cce7729c30f..17d4e1a326d31ca 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -76,8 +76,8 @@ struct PrintingPolicy {
         SuppressImplicitBase(false), FullyQualifiedName(false),
         PrintCanonicalTypes(false), PrintInjectedClassNameWithArguments(true),
         UsePreferredNames(true), AlwaysIncludeTypeForTemplateArgument(false),
-        CleanUglifiedParameters(false), EntireContentsOfLargeArray(true),
-        UseEnumerators(true) {}
+        UseClassForTemplateArgument(false), CleanUglifiedParameters(false),
+        EntireContentsOfLargeArray(true), UseEnumerators(true) {}
 
   /// Adjust this printing policy for cases where it's known that we're
   /// printing C++ code (for instance, if AST dumping reaches a C++-only
@@ -291,6 +291,10 @@ struct PrintingPolicy {
   /// parameters.
   unsigned AlwaysIncludeTypeForTemplateArgument : 1;
 
+  // Prints "class" keyword before type template arguments. This is used when
+  // printing a function via the _FUNCTION__ or __func__ macro in MSVC mode.
+  unsigned UseClassForTemplateArgument : 1;
+
   /// Whether to strip underscores when printing reserved parameter names.
   /// e.g. std::vector<class _Tp> becomes std::vector<class Tp>.
   /// This only affects parameter names, and so describes a compatible API.

>From dbcf81cf9e91e9b14470d9e18ac1dec2b3f6dfca Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Fri, 29 Sep 2023 10:51:51 -0700
Subject: [PATCH 04/11] Fixed a few issues.

---
 clang/lib/AST/Expr.cpp                 | 12 +++++++++---
 clang/lib/AST/TypePrinter.cpp          |  2 +-
 clang/test/SemaCXX/source_location.cpp | 12 ++++++++++++
 3 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 4eef890154e87b7..4157f8cf96dbbe9 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -773,8 +773,9 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
   }
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
     const auto &LO = Context.getLangOpts();
-    if (((IK == Function || IK == Func) && !LO.MicrosoftExt) ||
-        ((IK == LFunction || IK == Func) && LO.MicrosoftExt))
+    if (IK == Func || IK == Function && !LO.MicrosoftExt)
+      return FD->getNameAsString();
+    if (IK == LFunction && LO.MicrosoftExt)
       return FD->getNameAsString();
 
     SmallString<256> Name;
@@ -804,7 +805,6 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
     Policy.Callbacks = &PrettyCB;
     if (IK == Function && LO.MicrosoftExt) {
       Policy.UseClassForTemplateArgument = LO.MicrosoftExt;
-      Policy.MSVCFormatting = LO.MicrosoftExt;
     }
     std::string Proto;
     llvm::raw_string_ostream POut(Proto);
@@ -832,6 +832,12 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
 
     FD->printQualifiedName(POut, Policy);
 
+    if (IK == Function) {
+      POut.flush();
+      Out << Proto;
+      return std::string(Name);
+    }
+
     POut << "(";
     if (FT) {
       for (unsigned i = 0, e = Decl->getNumParams(); i != e; ++i) {
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 8a7cf85cdf126b6..83b73a67af4a4a5 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -2220,7 +2220,7 @@ printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,
       if (!FirstArg)
         OS << Comma;
 
-      if (Policy.MSVCFormatting && Policy.UseClassForTemplateArgument &&
+      if (Policy.UseClassForTemplateArgument &&
           Argument.getKind() == TemplateArgument::Type &&
           !Argument.getAsType()->isBuiltinType()) {
         const Type *Ty = Argument.getAsType().getTypePtr();
diff --git a/clang/test/SemaCXX/source_location.cpp b/clang/test/SemaCXX/source_location.cpp
index 29ce9c1697835df..d2b4856c1e83021 100644
--- a/clang/test/SemaCXX/source_location.cpp
+++ b/clang/test/SemaCXX/source_location.cpp
@@ -721,8 +721,16 @@ constexpr bool test_in_func() {
   static_assert(is_equal(b.a.f, "test_func_passed.cpp"));
   static_assert(is_equal(b.a.f2, "test_func_passed.cpp"));
   static_assert(is_equal(b.a.info.file(), "test_func_passed.cpp"));
+#ifdef MS
+  static_assert(is_equal(b.a.func, "test_out_of_line_init::test_in_func"));
+#else
   static_assert(is_equal(b.a.func, "test_in_func"));
+#endif
+#ifdef MS
+  static_assert(is_equal(b.a.func2, "test_out_of_line_init::test_in_func"));
+#else
   static_assert(is_equal(b.a.func2, "test_in_func"));
+#endif
   static_assert(is_equal(b.a.info.function(), "bool test_out_of_line_init::test_in_func()"));
   return true;
 }
@@ -749,7 +757,11 @@ constexpr InInit II;
 
 static_assert(II.l == 5200, "");
 static_assert(is_equal(II.f, "in_init.cpp"));
+#ifdef MS
+static_assert(is_equal(II.func, "test_global_scope::InInit::InInit"));
+#else
 static_assert(is_equal(II.func, "InInit"));
+#endif
 
 #line 5400
 struct AggInit {

>From e6708c0af2f81e734c39a0e38742d8f8f1f166f8 Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Sat, 30 Sep 2023 09:03:29 -0700
Subject: [PATCH 05/11] Fix LIT test literals.cpp.

---
 clang/test/AST/Interp/literals.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index ceda59405ea9105..a4af7ab29a91cd7 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -1046,7 +1046,7 @@ namespace PredefinedExprs {
     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(__FUNCTION__, "PredefinedExprs::foo"), "");
     static_assert(strings_match(__func__, "foo"), "");
     static_assert(strings_match(__PRETTY_FUNCTION__, "void PredefinedExprs::foo()"), "");
   }
@@ -1058,9 +1058,9 @@ namespace PredefinedExprs {
                                 // expected-warning {{result unused}}
     return __FUNCTION__[index];
   }
-  static_assert(heh(0) == 'h', "");
-  static_assert(heh(1) == 'e', "");
-  static_assert(heh(2) == 'h', "");
+  static_assert(heh(0) == 'P', "");
+  static_assert(heh(1) == 'r', "");
+  static_assert(heh(2) == 'e', "");
 #endif
 }
 

>From 473ff2b127bf22138ef6be4a74c16dca190c383d Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Sat, 30 Sep 2023 10:36:53 -0700
Subject: [PATCH 06/11] Reverted LIT Test.

---
 clang/test/CodeGenCXX/mangle-nttp-anon-union.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/test/CodeGenCXX/mangle-nttp-anon-union.cpp b/clang/test/CodeGenCXX/mangle-nttp-anon-union.cpp
index 1982a3eeb941291..4fd4a51bc3ee18e 100644
--- a/clang/test/CodeGenCXX/mangle-nttp-anon-union.cpp
+++ b/clang/test/CodeGenCXX/mangle-nttp-anon-union.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -std=c++20 -emit-llvm %s -o - -triple=x86_64-linux-gnu | FileCheck %s
-// RUN: %clang_cc1 -std=c++20 -emit-llvm %s -o - -triple=x86_64-linux-gnu | llvm-cxxfilt -n | FileCheck %s
+// RUN: %clang_cc1 -std=c++20 -fclang-abi-compat=latest -emit-llvm %s -o - -triple=x86_64-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 -std=c++20 -fclang-abi-compat=latest -emit-llvm %s -o - -triple=x86_64-linux-gnu | llvm-cxxfilt -n | FileCheck %s --check-prefix DEMANGLED
 
 template<typename T>
 struct wrapper1 {

>From 39c795ba37565c44235d5d615aabb0add84cc748 Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Mon, 2 Oct 2023 08:49:19 -0700
Subject: [PATCH 07/11] Added release note as requested by reviewer.

---
 clang/docs/ReleaseNotes.rst | 1 +
 1 file changed, 1 insertion(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 68172d5317a13ba..7b03e9a341e9acc 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -266,6 +266,7 @@ Bug Fixes in This Version
   (`#64836 <https://github.com/llvm/llvm-project/issues/64836>`_)
 - Clang now allows an ``_Atomic`` qualified integer in a switch statement. Fixes
   (`#65557 <https://github.com/llvm/llvm-project/issues/65557>`_)
+- Fix value of predefined macro ``__FUNCTION__`` to match MSVC's value. Fixes (`#66114 <https://github.com/llvm/llvm-project/issues/66114>`_)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

>From d64c4caf5a6534077158a096c3d88e8859baa462 Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Mon, 2 Oct 2023 13:37:19 -0700
Subject: [PATCH 08/11] Addressed review comments.

---
 clang/docs/ReleaseNotes.rst             |  3 ++-
 clang/include/clang/AST/PrettyPrinter.h |  8 ++++----
 clang/lib/AST/Expr.cpp                  |  2 +-
 clang/lib/AST/TypePrinter.cpp           | 27 ++++++++-----------------
 clang/test/SemaCXX/source_location.cpp  |  6 +++---
 5 files changed, 18 insertions(+), 28 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7b03e9a341e9acc..c805f2073f0038b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -266,7 +266,8 @@ Bug Fixes in This Version
   (`#64836 <https://github.com/llvm/llvm-project/issues/64836>`_)
 - Clang now allows an ``_Atomic`` qualified integer in a switch statement. Fixes
   (`#65557 <https://github.com/llvm/llvm-project/issues/65557>`_)
-- Fix value of predefined macro ``__FUNCTION__`` to match MSVC's value. Fixes (`#66114 <https://github.com/llvm/llvm-project/issues/66114>`_)
+- Fix value of predefined macro ``__FUNCTION__`` to match MSVC's value. Fixes
+  (`#66114 <https://github.com/llvm/llvm-project/issues/66114>`_)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index 17d4e1a326d31ca..f1216b4fd9861b7 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -76,7 +76,7 @@ struct PrintingPolicy {
         SuppressImplicitBase(false), FullyQualifiedName(false),
         PrintCanonicalTypes(false), PrintInjectedClassNameWithArguments(true),
         UsePreferredNames(true), AlwaysIncludeTypeForTemplateArgument(false),
-        UseClassForTemplateArgument(false), CleanUglifiedParameters(false),
+        ForcePrintingAsElaboratedType(false), CleanUglifiedParameters(false),
         EntireContentsOfLargeArray(true), UseEnumerators(true) {}
 
   /// Adjust this printing policy for cases where it's known that we're
@@ -291,9 +291,9 @@ struct PrintingPolicy {
   /// parameters.
   unsigned AlwaysIncludeTypeForTemplateArgument : 1;
 
-  // Prints "class" keyword before type template arguments. This is used when
-  // printing a function via the _FUNCTION__ or __func__ macro in MSVC mode.
-  unsigned UseClassForTemplateArgument : 1;
+  // Whether to print the type as an elaborated type. This is used when
+  // printing a function via the _FUNCTION__ macro in MSVC mode.
+  unsigned ForcePrintingAsElaboratedType : 1;
 
   /// Whether to strip underscores when printing reserved parameter names.
   /// e.g. std::vector<class _Tp> becomes std::vector<class Tp>.
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 4157f8cf96dbbe9..dd95b12c3a5952f 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -804,7 +804,7 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
     PrettyCallbacks PrettyCB(Context.getLangOpts());
     Policy.Callbacks = &PrettyCB;
     if (IK == Function && LO.MicrosoftExt) {
-      Policy.UseClassForTemplateArgument = LO.MicrosoftExt;
+      Policy.ForcePrintingAsElaboratedType = LO.MicrosoftExt;
     }
     std::string Proto;
     llvm::raw_string_ostream POut(Proto);
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 83b73a67af4a4a5..ee0159c1a020e13 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -2220,27 +2220,16 @@ printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,
       if (!FirstArg)
         OS << Comma;
 
-      if (Policy.UseClassForTemplateArgument &&
+      if (Policy.ForcePrintingAsElaboratedType &&
           Argument.getKind() == TemplateArgument::Type &&
-          !Argument.getAsType()->isBuiltinType()) {
-        const Type *Ty = Argument.getAsType().getTypePtr();
-        const char *kw;
-        if (Ty->isStructureType())
-          kw = "struct ";
-        else if (Ty->isClassType())
-          kw = "class ";
-        else if (Ty->isUnionType())
-          kw = "union ";
-        else if (Ty->isEnumeralType())
-          kw = "enum ";
-        else
-          llvm_unreachable("argument type not expected");
-        OS << kw;
+          !Argument.getAsType()->isBuiltinType())
+        OS << Argument.getAsType().getAsString().data();
+      else {
       }
-      // Tries to print the argument with location info if exists.
-      printArgument(Arg, Policy, ArgOS,
-                    TemplateParameterList::shouldIncludeTypeForArgument(
-                        Policy, TPL, ParmIndex));
+        // Tries to print the argument with location info if exists.
+        printArgument(Arg, Policy, ArgOS,
+                      TemplateParameterList::shouldIncludeTypeForArgument(
+                          Policy, TPL, ParmIndex));
     }
     StringRef ArgString = ArgOS.str();
 
diff --git a/clang/test/SemaCXX/source_location.cpp b/clang/test/SemaCXX/source_location.cpp
index d2b4856c1e83021..7c70aec84903a90 100644
--- a/clang/test/SemaCXX/source_location.cpp
+++ b/clang/test/SemaCXX/source_location.cpp
@@ -478,7 +478,7 @@ class TestBI {
       static_assert(is_equal(__FUNCTION__, "test_func::TestBI<int>::TestBI"));
       static_assert(is_equal(__func__, "TestBI"));
 #else
-      static_assert(is_equal(__func__, "TestBI"));
+      static_assert(is_equal(__FUNCTION__, "TestBI"));
       static_assert(is_equal(__func__, "TestBI"));
 #endif
    }
@@ -492,7 +492,7 @@ class TestClass {
       static_assert(is_equal(__FUNCTION__, "test_func::TestClass<class test_func::C>::TestClass"));
       static_assert(is_equal(__func__, "TestClass"));
 #else
-      static_assert(is_equal(__func__, "TestClass"));
+      static_assert(is_equal(__FUNCTION__, "TestClass"));
       static_assert(is_equal(__func__, "TestClass"));
 #endif
    }
@@ -520,7 +520,7 @@ class TestEnum {
       static_assert(is_equal(__FUNCTION__, "test_func::TestEnum<enum test_func::E>::TestEnum"));
       static_assert(is_equal(__func__, "TestEnum"));
 #else
-      static_assert(is_equal(__func__, "TestEnum"));
+      static_assert(is_equal(__FUNCTION__, "TestEnum"));
       static_assert(is_equal(__func__, "TestEnum"));
 #endif
    }

>From 45f78db1f47d8b22caecd983bc7e7161bcc15c16 Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Tue, 3 Oct 2023 10:58:00 -0700
Subject: [PATCH 09/11] Addressed review comments.

---
 clang/include/clang/AST/Expr.h         |  3 +-
 clang/lib/AST/Expr.cpp                 | 20 +++++++++-----
 clang/lib/AST/TypePrinter.cpp          |  3 +-
 clang/lib/Sema/SemaExpr.cpp            |  6 +++-
 clang/test/SemaCXX/source_location.cpp | 38 +++++++-------------------
 5 files changed, 31 insertions(+), 39 deletions(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 1c717b520dd87c6..530a2d92e666c29 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -2058,7 +2058,8 @@ class PredefinedExpr final
     return getIdentKindName(getIdentKind());
   }
 
-  static std::string ComputeName(IdentKind IK, const Decl *CurrentDecl);
+  static std::string ComputeName(IdentKind IK, const Decl *CurrentDecl,
+                                 bool ForceElaboratedPrinting = false);
 
   SourceLocation getBeginLoc() const { return getLocation(); }
   SourceLocation getEndLoc() const { return getLocation(); }
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index dd95b12c3a5952f..1979cdf6796357f 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -724,7 +724,8 @@ StringRef PredefinedExpr::getIdentKindName(PredefinedExpr::IdentKind IK) {
 
 // FIXME: Maybe this should use DeclPrinter with a special "print predefined
 // expr" policy instead.
-std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
+std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl,
+                                        bool ForceElaboratedPrinting) {
   ASTContext &Context = CurrentDecl->getASTContext();
 
   if (IK == PredefinedExpr::FuncDName) {
@@ -773,10 +774,16 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
   }
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
     const auto &LO = Context.getLangOpts();
-    if (IK == Func || IK == Function && !LO.MicrosoftExt)
-      return FD->getNameAsString();
-    if (IK == LFunction && LO.MicrosoftExt)
-      return FD->getNameAsString();
+    if (ForceElaboratedPrinting) {
+      if ((IK == Func || IK == Function) && !LO.MicrosoftExt)
+        return FD->getNameAsString();
+      if (IK == LFunction && LO.MicrosoftExt)
+        return FD->getNameAsString();
+    } else {
+      if (IK != PrettyFunction && IK != PrettyFunctionNoVirtual &&
+          IK != FuncSig && IK != LFuncSig)
+        return FD->getNameAsString();
+    }
 
     SmallString<256> Name;
     llvm::raw_svector_ostream Out(Name);
@@ -803,9 +810,8 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
     PrintingPolicy Policy(Context.getLangOpts());
     PrettyCallbacks PrettyCB(Context.getLangOpts());
     Policy.Callbacks = &PrettyCB;
-    if (IK == Function && LO.MicrosoftExt) {
+    if (IK == Function && ForceElaboratedPrinting)
       Policy.ForcePrintingAsElaboratedType = LO.MicrosoftExt;
-    }
     std::string Proto;
     llvm::raw_string_ostream POut(Proto);
 
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index ee0159c1a020e13..ac420bca3e4b026 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -2224,8 +2224,7 @@ printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,
           Argument.getKind() == TemplateArgument::Type &&
           !Argument.getAsType()->isBuiltinType())
         OS << Argument.getAsType().getAsString().data();
-      else {
-      }
+      else
         // Tries to print the argument with location info if exists.
         printArgument(Arg, Policy, ArgOS,
                       TemplateParameterList::shouldIncludeTypeForArgument(
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 92496b03ecabe54..b77c49aa013e32e 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -3727,7 +3727,11 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
   else {
     // Pre-defined identifiers are of type char[x], where x is the length of
     // the string.
-    auto Str = PredefinedExpr::ComputeName(IK, currentDecl);
+    bool ForceElaboratedPrinting = false;
+    if (IK == PredefinedExpr::IdentKind::Function && getLangOpts().MicrosoftExt)
+      ForceElaboratedPrinting = true;
+    auto Str =
+        PredefinedExpr::ComputeName(IK, currentDecl, ForceElaboratedPrinting);
     unsigned Length = Str.length();
 
     llvm::APInt LengthI(32, Length + 1);
diff --git a/clang/test/SemaCXX/source_location.cpp b/clang/test/SemaCXX/source_location.cpp
index 7c70aec84903a90..2e38a8e0bebf2b8 100644
--- a/clang/test/SemaCXX/source_location.cpp
+++ b/clang/test/SemaCXX/source_location.cpp
@@ -423,17 +423,10 @@ constexpr const char *test_func_simple(const char *__f = __builtin_FUNCTION()) {
 constexpr const char *get_function() {
   return __func__;
 }
-#ifdef MS
 constexpr bool test_function() {
-  return !is_equal(__func__, test_func_simple()) &&
-         !is_equal(get_function(), test_func_simple());
-}
-#else
-  constexpr bool test_function() {
   return is_equal(__func__, test_func_simple()) &&
          !is_equal(get_function(), test_func_simple());
 }
-#endif
 static_assert(test_function());
 
 template <class T, class U = SL>
@@ -475,11 +468,11 @@ class TestBI {
 public:
    TestBI() {
 #ifdef MS
-      static_assert(is_equal(__FUNCTION__, "test_func::TestBI<int>::TestBI"));
-      static_assert(is_equal(__func__, "TestBI"));
+     static_assert(is_equal(__FUNCTION__, "test_func::TestBI<int>::TestBI"));
+     static_assert(is_equal(__func__, "TestBI"));
 #else
-      static_assert(is_equal(__FUNCTION__, "TestBI"));
-      static_assert(is_equal(__func__, "TestBI"));
+     static_assert(is_equal(__FUNCTION__, "TestBI"));
+     static_assert(is_equal(__func__, "TestBI"));
 #endif
    }
 };
@@ -506,7 +499,7 @@ class TestStruct {
       static_assert(is_equal(__FUNCTION__, "test_func::TestStruct<struct test_func::S>::TestStruct"));
       static_assert(is_equal(__func__, "TestStruct"));
 #else
-      static_assert(is_equal(__func__, "TestStruct"));
+      static_assert(is_equal(__FUNCTION__, "TestStruct"));
       static_assert(is_equal(__func__, "TestStruct"));
 #endif
    }
@@ -530,12 +523,13 @@ class C {};
 struct S {};
 enum E {};
 
-test_func::TestBI<int> t1;
-test_func::TestClass<C> t2;
-test_func::TestStruct<S> t3;
-test_func::TestEnum<E> t4;
+
 } // namespace test_func
 
+test_func::TestBI<int> t1;
+test_func::TestClass<test_func::C> t2;
+test_func::TestStruct<test_func::S> t3;
+test_func::TestEnum<test_func::E> t4;
 
 //===----------------------------------------------------------------------===//
 //                            __builtin_FUNCSIG()
@@ -721,16 +715,8 @@ constexpr bool test_in_func() {
   static_assert(is_equal(b.a.f, "test_func_passed.cpp"));
   static_assert(is_equal(b.a.f2, "test_func_passed.cpp"));
   static_assert(is_equal(b.a.info.file(), "test_func_passed.cpp"));
-#ifdef MS
-  static_assert(is_equal(b.a.func, "test_out_of_line_init::test_in_func"));
-#else
   static_assert(is_equal(b.a.func, "test_in_func"));
-#endif
-#ifdef MS
-  static_assert(is_equal(b.a.func2, "test_out_of_line_init::test_in_func"));
-#else
   static_assert(is_equal(b.a.func2, "test_in_func"));
-#endif
   static_assert(is_equal(b.a.info.function(), "bool test_out_of_line_init::test_in_func()"));
   return true;
 }
@@ -757,11 +743,7 @@ constexpr InInit II;
 
 static_assert(II.l == 5200, "");
 static_assert(is_equal(II.f, "in_init.cpp"));
-#ifdef MS
-static_assert(is_equal(II.func, "test_global_scope::InInit::InInit"));
-#else
 static_assert(is_equal(II.func, "InInit"));
-#endif
 
 #line 5400
 struct AggInit {

>From 998bc11f0e2e252a1c711ffc21d58c7df864f8dd Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Tue, 3 Oct 2023 11:01:51 -0700
Subject: [PATCH 10/11] Cleaned up RN file.

---
 clang/docs/ReleaseNotes.rst | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index d2ab32e52e17ba4..4d6479c0147d73c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -281,7 +281,6 @@ Bug Fixes in This Version
   Fixes (`#67603 <https://github.com/llvm/llvm-project/issues/67603>`_)
 - Fixes a crash caused by a multidimensional array being captured by a lambda
   (`#67722 <https://github.com/llvm/llvm-project/issues/67722>`_).
->>>>>>> e271bc1be7ea5b160f70cff28d7d50e03b7a6ca8
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

>From a564cdabd9be9e99f457d7143f71ea3dd5a7eb27 Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Wed, 4 Oct 2023 05:10:52 -0700
Subject: [PATCH 11/11] Fix format in RN.

---
 clang/docs/ReleaseNotes.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 4d6479c0147d73c..9b6bc160fa93101 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -274,7 +274,7 @@ Bug Fixes in This Version
   (`#62945 <https://github.com/llvm/llvm-project/issues/62945>`_)
 - Clang now allows an ``_Atomic`` qualified integer in a switch statement. Fixes
   (`#65557 <https://github.com/llvm/llvm-project/issues/65557>`_)
-- Fix value of predefined macro ``__FUNCTION__`` to match MSVC's value. Fixes 
+- Fix value of predefined macro ``__FUNCTION__`` to match MSVC's value. Fixes
   (`#66114 <https://github.com/llvm/llvm-project/issues/66114>`_)
 - Fixes crash when trying to obtain the common sugared type of
   `decltype(instantiation-dependent-expr)`.



More information about the cfe-commits mailing list