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

Zahira Ammarguellat via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 6 05:13:57 PST 2024


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

>From bdefe754c14c5e050ebf2b9c82eca458041564a4 Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Tue, 5 Mar 2024 05:35:16 -0800
Subject: [PATCH 1/4] [clang-cl] Fix value of __FUNCTION__ in MSVC mode.

---
 clang/docs/ReleaseNotes.rst                   |  3 +
 clang/include/clang/AST/Expr.h                |  3 +-
 clang/lib/AST/Expr.cpp                        | 26 ++++++--
 clang/lib/AST/TypePrinter.cpp                 | 24 +++++--
 clang/lib/Sema/SemaExpr.cpp                   |  5 +-
 clang/test/AST/Interp/literals.cpp            |  8 +--
 clang/test/Analysis/eval-predefined-exprs.cpp | 22 +++++--
 clang/test/SemaCXX/source_location.cpp        | 64 +++++++++++++++++++
 clang/unittests/AST/DeclPrinterTest.cpp       | 15 +++++
 9 files changed, 149 insertions(+), 21 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 612b4329727455..20c14fae1dd31b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -224,6 +224,9 @@ Bug Fixes in This Version
   for variables created through copy initialization having side-effects in C++17 and later.
   Fixes (#GH64356) (#GH79518).
 
+- 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/Expr.h b/clang/include/clang/AST/Expr.h
index bf0622bdeca30e..ce8e64a4bed04b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -2034,7 +2034,8 @@ class PredefinedExpr final
   }
 
   static std::string ComputeName(PredefinedIdentKind IK,
-                                 const Decl *CurrentDecl);
+                                 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 b4de2155adcebd..796e50817ee319 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -673,7 +673,8 @@ StringRef PredefinedExpr::getIdentKindName(PredefinedIdentKind IK) {
 // FIXME: Maybe this should use DeclPrinter with a special "print predefined
 // expr" policy instead.
 std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK,
-                                        const Decl *CurrentDecl) {
+                                        const Decl *CurrentDecl,
+                                        bool ForceElaboratedPrinting) {
   ASTContext &Context = CurrentDecl->getASTContext();
 
   if (IK == PredefinedIdentKind::FuncDName) {
@@ -721,10 +722,17 @@ std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK,
     return std::string(Out.str());
   }
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
-    if (IK != PredefinedIdentKind::PrettyFunction &&
-        IK != PredefinedIdentKind::PrettyFunctionNoVirtual &&
-        IK != PredefinedIdentKind::FuncSig &&
-        IK != PredefinedIdentKind::LFuncSig)
+    const auto &LO = Context.getLangOpts();
+    if ((ForceElaboratedPrinting &&
+         (((IK == PredefinedIdentKind::Func ||
+            IK == PredefinedIdentKind ::Function) &&
+           !LO.MicrosoftExt) ||
+          (IK == PredefinedIdentKind::LFunction && LO.MicrosoftExt))) ||
+        (!ForceElaboratedPrinting &&
+         (IK != PredefinedIdentKind::PrettyFunction &&
+          IK != PredefinedIdentKind::PrettyFunctionNoVirtual &&
+          IK != PredefinedIdentKind::FuncSig &&
+          IK != PredefinedIdentKind::LFuncSig)))
       return FD->getNameAsString();
 
     SmallString<256> Name;
@@ -752,6 +760,8 @@ std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK,
     PrintingPolicy Policy(Context.getLangOpts());
     PrettyCallbacks PrettyCB(Context.getLangOpts());
     Policy.Callbacks = &PrettyCB;
+    if (IK == PredefinedIdentKind::Function && ForceElaboratedPrinting)
+      Policy.SuppressTagKeyword = !LO.MicrosoftExt;
     std::string Proto;
     llvm::raw_string_ostream POut(Proto);
 
@@ -779,6 +789,12 @@ std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK,
 
     FD->printQualifiedName(POut, Policy);
 
+    if (IK == PredefinedIdentKind::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 7dcc4348f8e036..21605e1f53e3d9 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1635,6 +1635,17 @@ void TypePrinter::printElaboratedBefore(const ElaboratedType *T,
     if (T->getKeyword() != ElaboratedTypeKeyword::None)
       OS << " ";
     NestedNameSpecifier *Qualifier = T->getQualifier();
+    if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
+        !Policy.SuppressUnwrittenScope) {
+      std::string prefix = T->isClassType()       ? "class "
+                           : T->isStructureType() ? "struct "
+                           : T->isUnionType()     ? "union "
+                                                  : "";
+      OS << prefix;
+      Policy.SuppressTagKeyword = true;
+      Policy.SuppressScope = false;
+      return printBefore(T->getNamedType(), OS);
+    }
     if (Qualifier)
       Qualifier->print(OS, Policy);
   }
@@ -2260,10 +2271,15 @@ printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,
     } else {
       if (!FirstArg)
         OS << Comma;
-      // Tries to print the argument with location info if exists.
-      printArgument(Arg, Policy, ArgOS,
-                    TemplateParameterList::shouldIncludeTypeForArgument(
-                        Policy, TPL, ParmIndex));
+      if (!Policy.SuppressTagKeyword &&
+          Argument.getKind() == TemplateArgument::Type &&
+          isa<TagType>(Argument.getAsType()))
+        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));
     }
     StringRef ArgString = ArgOS.str();
 
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 0a449fc1082bd4..fa0daa8ab0491b 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -3741,7 +3741,10 @@ 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 =
+        IK == PredefinedIdentKind::Function && getLangOpts().MicrosoftExt;
+    auto Str =
+        PredefinedExpr::ComputeName(IK, currentDecl, ForceElaboratedPrinting);
     unsigned Length = Str.length();
 
     llvm::APInt LengthI(32, Length + 1);
diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index d86609108ca446..b2f3f2cf7e336f 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -1039,7 +1039,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()"), "");
   }
@@ -1049,9 +1049,9 @@ namespace PredefinedExprs {
     __extension__ __FUNCTION__; // both-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
 }
 
diff --git a/clang/test/Analysis/eval-predefined-exprs.cpp b/clang/test/Analysis/eval-predefined-exprs.cpp
index 1eec4476a065f3..a6bac5ee9d486d 100644
--- a/clang/test/Analysis/eval-predefined-exprs.cpp
+++ b/clang/test/Analysis/eval-predefined-exprs.cpp
@@ -55,9 +55,14 @@ struct A {
     clang_analyzer_dump(__func__);
     clang_analyzer_dump(__FUNCTION__);
     clang_analyzer_dump(__PRETTY_FUNCTION__);
-    // expected-warning at -3 {{&Element{"A",0 S64b,char}}}
-    // expected-warning at -3 {{&Element{"A",0 S64b,char}}}
-    // expected-warning at -3 {{&Element{"A::A()",0 S64b,char}}}
+#ifdef ANALYZER_MS
+    // 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}}}
+    // expected-warning at -7 {{&Element{"A",0 S64b,char}}}
+#endif
+    // expected-warning at -8 {{&Element{"A::A()",0 S64b,char}}}
 
 #ifdef ANALYZER_MS
     clang_analyzer_dump(__FUNCDNAME__);
@@ -74,9 +79,14 @@ struct A {
     clang_analyzer_dump(__func__);
     clang_analyzer_dump(__FUNCTION__);
     clang_analyzer_dump(__PRETTY_FUNCTION__);
-    // expected-warning at -3 {{&Element{"~A",0 S64b,char}}}
-    // expected-warning at -3 {{&Element{"~A",0 S64b,char}}}
-    // expected-warning at -3 {{&Element{"A::~A()",0 S64b,char}}}
+#ifdef ANALYZER_MS
+    // 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}}}
+    // expected-warning at -7 {{&Element{"~A",0 S64b,char}}}
+#endif
+    // expected-warning at -8 {{&Element{"A::~A()",0 S64b,char}}}
 
 #ifdef ANALYZER_MS
     clang_analyzer_dump(__FUNCDNAME__);
diff --git a/clang/test/SemaCXX/source_location.cpp b/clang/test/SemaCXX/source_location.cpp
index 7414fbce7828d1..203925cf49e936 100644
--- a/clang/test/SemaCXX/source_location.cpp
+++ b/clang/test/SemaCXX/source_location.cpp
@@ -463,8 +463,72 @@ 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(__FUNCTION__, "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(__FUNCTION__, "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(__FUNCTION__, "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(__FUNCTION__, "TestEnum"));
+      static_assert(is_equal(__func__, "TestEnum"));
+#endif
+   }
+};
+
+class C {};
+struct S {};
+enum E {};
 } // 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()
 //===----------------------------------------------------------------------===//
diff --git a/clang/unittests/AST/DeclPrinterTest.cpp b/clang/unittests/AST/DeclPrinterTest.cpp
index 0e09ab2a7bba88..8fcfaa7c2f0379 100644
--- a/clang/unittests/AST/DeclPrinterTest.cpp
+++ b/clang/unittests/AST/DeclPrinterTest.cpp
@@ -358,6 +358,21 @@ TEST(DeclPrinter, TestCXXRecordDecl11) {
     "class A : virtual public Z, private Y {}"));
 }
 
+TEST(DeclPrinter, TestCXXRecordDecl12) {
+  ASSERT_TRUE(PrintedDeclCXX98Matches(
+      "struct S { int x; };"
+      "namespace NS { class C {};}"
+      "S foo(S s1, NS::C c1) {using namespace NS; C c; return s1;}",
+      "foo",
+      "struct S foo(struct S s1, class NS::C c1) {\nusing namespace NS;\nclass "
+      "NS::C c;\nreturn s1;\n}\n",
+      [](PrintingPolicy &Policy) {
+        Policy.SuppressTagKeyword = false;
+        Policy.SuppressScope = true;
+        Policy.TerseOutput = false;
+      }));
+}
+
 TEST(DeclPrinter, TestFunctionDecl1) {
   ASSERT_TRUE(PrintedDeclCXX98Matches(
     "void A();",

>From 13f46938be7deaf0ae0409e374694b61e2ffe86d Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Tue, 5 Mar 2024 14:18:39 -0800
Subject: [PATCH 2/4] Addressed review comments.

---
 clang/lib/AST/Expr.cpp                        | 24 ++++++++------
 clang/lib/AST/TypePrinter.cpp                 | 10 +++---
 clang/lib/Sema/SemaExpr.cpp                   |  2 +-
 clang/test/AST/Interp/literals.cpp            |  8 ++---
 clang/test/Analysis/eval-predefined-exprs.cpp | 32 +++++++++----------
 clang/test/SemaCXX/source_location.cpp        | 30 ++++++++---------
 6 files changed, 54 insertions(+), 52 deletions(-)

diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 796e50817ee319..c2524b2df0fe2a 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -723,16 +723,20 @@ std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK,
   }
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
     const auto &LO = Context.getLangOpts();
+    bool isFuncOrFunctionInNonMSVCCompatEnv =
+        ((IK == PredefinedIdentKind::Func ||
+          IK == PredefinedIdentKind ::Function) &&
+         !LO.MSVCCompat);
+    bool isLFunctionInMSVCCommpatEnv =
+        IK == PredefinedIdentKind::LFunction && LO.MSVCCompat;
+    bool isFuncOrFunctionOrLFunctionOrFuncDName =
+        IK != PredefinedIdentKind::PrettyFunction &&
+        IK != PredefinedIdentKind::PrettyFunctionNoVirtual &&
+        IK != PredefinedIdentKind::FuncSig &&
+        IK != PredefinedIdentKind::LFuncSig;
     if ((ForceElaboratedPrinting &&
-         (((IK == PredefinedIdentKind::Func ||
-            IK == PredefinedIdentKind ::Function) &&
-           !LO.MicrosoftExt) ||
-          (IK == PredefinedIdentKind::LFunction && LO.MicrosoftExt))) ||
-        (!ForceElaboratedPrinting &&
-         (IK != PredefinedIdentKind::PrettyFunction &&
-          IK != PredefinedIdentKind::PrettyFunctionNoVirtual &&
-          IK != PredefinedIdentKind::FuncSig &&
-          IK != PredefinedIdentKind::LFuncSig)))
+         (isFuncOrFunctionInNonMSVCCompatEnv || isLFunctionInMSVCCommpatEnv)) ||
+        !ForceElaboratedPrinting && isFuncOrFunctionOrLFunctionOrFuncDName)
       return FD->getNameAsString();
 
     SmallString<256> Name;
@@ -761,7 +765,7 @@ std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK,
     PrettyCallbacks PrettyCB(Context.getLangOpts());
     Policy.Callbacks = &PrettyCB;
     if (IK == PredefinedIdentKind::Function && ForceElaboratedPrinting)
-      Policy.SuppressTagKeyword = !LO.MicrosoftExt;
+      Policy.SuppressTagKeyword = !LO.MSVCCompat;
     std::string Proto;
     llvm::raw_string_ostream POut(Proto);
 
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 21605e1f53e3d9..6de90638d916cf 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1637,10 +1637,10 @@ void TypePrinter::printElaboratedBefore(const ElaboratedType *T,
     NestedNameSpecifier *Qualifier = T->getQualifier();
     if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
         !Policy.SuppressUnwrittenScope) {
-      std::string prefix = T->isClassType()       ? "class "
-                           : T->isStructureType() ? "struct "
-                           : T->isUnionType()     ? "union "
-                                                  : "";
+      StringRef prefix = T->isClassType()       ? "class "
+                         : T->isStructureType() ? "struct "
+                         : T->isUnionType()     ? "union "
+                                                : "";
       OS << prefix;
       Policy.SuppressTagKeyword = true;
       Policy.SuppressScope = false;
@@ -2274,7 +2274,7 @@ printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,
       if (!Policy.SuppressTagKeyword &&
           Argument.getKind() == TemplateArgument::Type &&
           isa<TagType>(Argument.getAsType()))
-        OS << Argument.getAsType().getAsString().data();
+        OS << Argument.getAsType().getAsString();
       else
         // Tries to print the argument with location info if exists.
         printArgument(Arg, Policy, ArgOS,
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index fa0daa8ab0491b..c80f1dd810e732 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -3742,7 +3742,7 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
     // Pre-defined identifiers are of type char[x], where x is the length of
     // the string.
     bool ForceElaboratedPrinting =
-        IK == PredefinedIdentKind::Function && getLangOpts().MicrosoftExt;
+        IK == PredefinedIdentKind::Function && getLangOpts().MSVCCompat;
     auto Str =
         PredefinedExpr::ComputeName(IK, currentDecl, ForceElaboratedPrinting);
     unsigned Length = Str.length();
diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index b2f3f2cf7e336f..d86609108ca446 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -1039,7 +1039,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__, "PredefinedExprs::foo"), "");
+    static_assert(strings_match(__FUNCTION__, "foo"), "");
     static_assert(strings_match(__func__, "foo"), "");
     static_assert(strings_match(__PRETTY_FUNCTION__, "void PredefinedExprs::foo()"), "");
   }
@@ -1049,9 +1049,9 @@ namespace PredefinedExprs {
     __extension__ __FUNCTION__; // both-warning {{result unused}}
     return __FUNCTION__[index];
   }
-  static_assert(heh(0) == 'P', "");
-  static_assert(heh(1) == 'r', "");
-  static_assert(heh(2) == 'e', "");
+  static_assert(heh(0) == 'h', "");
+  static_assert(heh(1) == 'e', "");
+  static_assert(heh(2) == 'h', "");
 #endif
 }
 
diff --git a/clang/test/Analysis/eval-predefined-exprs.cpp b/clang/test/Analysis/eval-predefined-exprs.cpp
index a6bac5ee9d486d..1a407597eb96b7 100644
--- a/clang/test/Analysis/eval-predefined-exprs.cpp
+++ b/clang/test/Analysis/eval-predefined-exprs.cpp
@@ -52,17 +52,17 @@ void foo() {
 
 struct A {
   A() {
-    clang_analyzer_dump(__func__);
-    clang_analyzer_dump(__FUNCTION__);
-    clang_analyzer_dump(__PRETTY_FUNCTION__);
 #ifdef ANALYZER_MS
-    // expected-warning at -4 {{&Element{"A",0 S64b,char}}}
-    // expected-warning at -4 {{&Element{"A::A",0 S64b,char}}}
+    clang_analyzer_dump(__func__);     // expected-warning {{&Element{"A",0 S64b,char}}}
 #else
-    // expected-warning at -7 {{&Element{"A",0 S64b,char}}}
-    // expected-warning at -7 {{&Element{"A",0 S64b,char}}}
+        clang_analyzer_dump(__func__); // expected-warning {{&Element{"A",0 S64b,char}}}
 #endif
-    // expected-warning at -8 {{&Element{"A::A()",0 S64b,char}}}
+#ifdef ANALYZER_MS
+    clang_analyzer_dump(__FUNCTION__); // expected-warning {{&Element{"A::A",0 S64b,char}}}
+#else
+    clang_analyzer_dump(__FUNCTION__); // expected-warning {{&Element{"A",0 S64b,char}}}
+#endif
+    clang_analyzer_dump(__PRETTY_FUNCTION__);  // expected-warning {{&Element{"A::A()",0 S64b,char}}}
 
 #ifdef ANALYZER_MS
     clang_analyzer_dump(__FUNCDNAME__);
@@ -76,17 +76,17 @@ struct A {
 #endif
   }
   ~A() {
-    clang_analyzer_dump(__func__);
-    clang_analyzer_dump(__FUNCTION__);
-    clang_analyzer_dump(__PRETTY_FUNCTION__);
 #ifdef ANALYZER_MS
-    // expected-warning at -4 {{&Element{"~A",0 S64b,char}}}
-    // expected-warning at -4 {{&Element{"A::~A",0 S64b,char}}}
+    clang_analyzer_dump(__func__);          // expected-warning {{&Element{"~A",0 S64b,char}}}
+#else
+    clang_analyzer_dump(__func__);          // expected-warning {{&Element{"~A",0 S64b,char}}}
+#endif
+#ifdef ANALYZER_MS
+    clang_analyzer_dump(__FUNCTION__);      // expected-warning {{&Element{"A::~A",0 S64b,char}}}
 #else
-    // expected-warning at -7 {{&Element{"~A",0 S64b,char}}}
-    // expected-warning at -7 {{&Element{"~A",0 S64b,char}}}
+    clang_analyzer_dump(__FUNCTION__);      // expected-warning {{&Element{"~A",0 S64b,char}}}
 #endif
-    // expected-warning at -8 {{&Element{"A::~A()",0 S64b,char}}}
+    clang_analyzer_dump(__PRETTY_FUNCTION__); // expected-warning {{&Element{"A::~A()",0 S64b,char}}}
 
 #ifdef ANALYZER_MS
     clang_analyzer_dump(__FUNCDNAME__);
diff --git a/clang/test/SemaCXX/source_location.cpp b/clang/test/SemaCXX/source_location.cpp
index 203925cf49e936..d6c377bcd4d31f 100644
--- a/clang/test/SemaCXX/source_location.cpp
+++ b/clang/test/SemaCXX/source_location.cpp
@@ -1,14 +1,14 @@
 // RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fexceptions -verify %s
 // RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -DUSE_CONSTEVAL -fexceptions -verify %s
 // RUN: %clang_cc1 -std=c++2b -fcxx-exceptions -DUSE_CONSTEVAL -DPAREN_INIT -fexceptions -verify %s
-// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fms-extensions -DMS -fexceptions -verify %s
-// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -fms-extensions -DMS -DUSE_CONSTEVAL -fexceptions -verify %s
+// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fms-extensions -DMS -fexceptions -fms-compatibility -verify %s
+// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -fms-extensions -DMS -DUSE_CONSTEVAL -fexceptions -fms-compatibility -verify %s
 //
 // RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
 // RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -DUSE_CONSTEVAL -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
 // RUN: %clang_cc1 -std=c++2b -fcxx-exceptions -DUSE_CONSTEVAL -DPAREN_INIT -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
-// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fms-extensions -DMS -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
-// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -fms-extensions -DMS -DUSE_CONSTEVAL -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
+// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fms-extensions -DMS -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -fms-compatibility -verify %s
+// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -fms-extensions -DMS -DUSE_CONSTEVAL -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify -fms-compatibility %s
 // expected-no-diagnostics
 
 #define assert(...) ((__VA_ARGS__) ? ((void)0) : throw 42)
@@ -469,11 +469,10 @@ class TestBI {
    TestBI() {
 #ifdef MS
      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"));
 #endif
+     static_assert(is_equal(__func__, "TestBI"));
    }
 };
 
@@ -483,11 +482,10 @@ class TestClass {
    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(__FUNCTION__, "TestClass"));
-      static_assert(is_equal(__func__, "TestClass"));
 #endif
+      static_assert(is_equal(__func__, "TestClass"));
    }
 };
 
@@ -497,11 +495,10 @@ class TestStruct {
    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(__FUNCTION__, "TestStruct"));
-      static_assert(is_equal(__func__, "TestStruct"));
 #endif
+      static_assert(is_equal(__func__, "TestStruct"));
    }
 };
 
@@ -511,23 +508,24 @@ class TestEnum {
    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(__FUNCTION__, "TestEnum"));
-      static_assert(is_equal(__func__, "TestEnum"));
 #endif
+      static_assert(is_equal(__func__, "TestEnum"));
    }
 };
 
 class C {};
 struct S {};
 enum E {};
+
+TestBI<int> t1;
+TestClass<test_func::C> t2;
+TestStruct<test_func::S> t3;
+TestEnum<test_func::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()

>From 5eeffd1762e2cba336753ee2fedfce1620356bf2 Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Wed, 6 Mar 2024 04:41:05 -0800
Subject: [PATCH 3/4] Addressed review comments.

---
 clang/docs/ReleaseNotes.rst                   | 4 ++--
 clang/test/Analysis/eval-predefined-exprs.cpp | 8 --------
 2 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 20c14fae1dd31b..db5f7aa39388e7 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -224,8 +224,8 @@ Bug Fixes in This Version
   for variables created through copy initialization having side-effects in C++17 and later.
   Fixes (#GH64356) (#GH79518).
 
-- 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__`` in MSVC compatibility mode.
+  Fixes (GH#66114).
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/test/Analysis/eval-predefined-exprs.cpp b/clang/test/Analysis/eval-predefined-exprs.cpp
index 1a407597eb96b7..b26091869cd03f 100644
--- a/clang/test/Analysis/eval-predefined-exprs.cpp
+++ b/clang/test/Analysis/eval-predefined-exprs.cpp
@@ -52,11 +52,7 @@ void foo() {
 
 struct A {
   A() {
-#ifdef ANALYZER_MS
     clang_analyzer_dump(__func__);     // expected-warning {{&Element{"A",0 S64b,char}}}
-#else
-        clang_analyzer_dump(__func__); // expected-warning {{&Element{"A",0 S64b,char}}}
-#endif
 #ifdef ANALYZER_MS
     clang_analyzer_dump(__FUNCTION__); // expected-warning {{&Element{"A::A",0 S64b,char}}}
 #else
@@ -76,11 +72,7 @@ struct A {
 #endif
   }
   ~A() {
-#ifdef ANALYZER_MS
     clang_analyzer_dump(__func__);          // expected-warning {{&Element{"~A",0 S64b,char}}}
-#else
-    clang_analyzer_dump(__func__);          // expected-warning {{&Element{"~A",0 S64b,char}}}
-#endif
 #ifdef ANALYZER_MS
     clang_analyzer_dump(__FUNCTION__);      // expected-warning {{&Element{"A::~A",0 S64b,char}}}
 #else

>From 16d3c751336a9d4127793cd02a5de838baa3859c Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Wed, 6 Mar 2024 05:13:32 -0800
Subject: [PATCH 4/4] Fixed typo.

---
 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 db5f7aa39388e7..0399d5ab6b16a4 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -225,7 +225,7 @@ Bug Fixes in This Version
   Fixes (#GH64356) (#GH79518).
 
 - Fix value of predefined macro ``__FUNCTION__`` in MSVC compatibility mode.
-  Fixes (GH#66114).
+  Fixes (#GH66114).
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^



More information about the cfe-commits mailing list