[llvm] [clang-cl] Fix value of __FUNCTION__ and __func__ in MSVC mode. (PR #67592)
Zahira Ammarguellat via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 27 12:12:02 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 1/2] 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 2/2] 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 {};
More information about the llvm-commits
mailing list