[clang] [clang-cl] Fix for __FUNCTION__ in c++. (PR #66120)
Zahira Ammarguellat via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 19 11:47:14 PDT 2023
https://github.com/zahiraam updated https://github.com/llvm/llvm-project/pull/66120
>From 3fcfa303bd211f9a3382657012968cd3f7269db8 Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Tue, 12 Sep 2023 11:25:19 -0700
Subject: [PATCH 1/3] [clang-cl] Fix for __FUNCTION__ in c++.
---
clang/lib/AST/Expr.cpp | 20 ++++++++++++++++++++
clang/lib/AST/TypePrinter.cpp | 4 ++++
2 files changed, 24 insertions(+)
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 4f3837371b3fc5e..55b6e2968487b86 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -727,6 +727,26 @@ StringRef PredefinedExpr::getIdentKindName(PredefinedExpr::IdentKind IK) {
std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
ASTContext &Context = CurrentDecl->getASTContext();
+ if (CurrentDecl->getASTContext().getTargetInfo().getCXXABI().isMicrosoft() &&
+ IK == PredefinedExpr::Function) {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
+ SmallString<256> Name;
+ llvm::raw_svector_ostream Out(Name);
+ PrintingPolicy Policy(Context.getLangOpts());
+ Policy.AlwaysIncludeTypeForTemplateArgument = true;
+ std::string Proto;
+ llvm::raw_string_ostream POut(Proto);
+ const FunctionDecl *Decl = FD;
+ if (const FunctionDecl *Pattern = FD->getTemplateInstantiationPattern())
+ Decl = Pattern;
+ const FunctionType *AFT = Decl->getType()->getAs<FunctionType>();
+ const FunctionProtoType *FT = nullptr;
+ if (FD->hasWrittenPrototype())
+ FT = dyn_cast<FunctionProtoType>(AFT);
+ FD->printQualifiedName(POut, Policy);
+ return std::string(POut.str());
+ }
+ }
if (IK == PredefinedExpr::FuncDName) {
if (const NamedDecl *ND = dyn_cast<NamedDecl>(CurrentDecl)) {
std::unique_ptr<MangleContext> MC;
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index eb69d0bb8755b48..676ce166312adf4 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -2218,6 +2218,10 @@ printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,
} else {
if (!FirstArg)
OS << Comma;
+ // zahira
+ //if (Argument.getKind() == TemplateArgument::Type)
+ // OS << "class ";
+
// Tries to print the argument with location info if exists.
printArgument(Arg, Policy, ArgOS,
TemplateParameterList::shouldIncludeTypeForArgument(
>From f2c2d9ca4120d61e8cf75165693ead19890be0e0 Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Wed, 13 Sep 2023 06:45:03 -0700
Subject: [PATCH 2/3] Testing.
---
clang/lib/AST/TypePrinter.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 676ce166312adf4..e4abf4b2160682a 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -2218,7 +2218,6 @@ printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,
} else {
if (!FirstArg)
OS << Comma;
- // zahira
//if (Argument.getKind() == TemplateArgument::Type)
// OS << "class ";
>From 5e85929ce09c0c73b10c5557ee14f431f8a59808 Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Tue, 19 Sep 2023 11:44:16 -0700
Subject: [PATCH 3/3] Addressed review comments.
---
clang/lib/AST/Expr.cpp | 47 +++++++++--------------
clang/lib/AST/TypePrinter.cpp | 4 +-
clang/test/CodeGenCXX/predefined-expr.cpp | 19 +++++++++
clang/test/SemaCXX/source_location.cpp | 12 ++++++
4 files changed, 51 insertions(+), 31 deletions(-)
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 55b6e2968487b86..4d258c92dda3012 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -727,26 +727,6 @@ StringRef PredefinedExpr::getIdentKindName(PredefinedExpr::IdentKind IK) {
std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
ASTContext &Context = CurrentDecl->getASTContext();
- if (CurrentDecl->getASTContext().getTargetInfo().getCXXABI().isMicrosoft() &&
- IK == PredefinedExpr::Function) {
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
- SmallString<256> Name;
- llvm::raw_svector_ostream Out(Name);
- PrintingPolicy Policy(Context.getLangOpts());
- Policy.AlwaysIncludeTypeForTemplateArgument = true;
- std::string Proto;
- llvm::raw_string_ostream POut(Proto);
- const FunctionDecl *Decl = FD;
- if (const FunctionDecl *Pattern = FD->getTemplateInstantiationPattern())
- Decl = Pattern;
- const FunctionType *AFT = Decl->getType()->getAs<FunctionType>();
- const FunctionProtoType *FT = nullptr;
- if (FD->hasWrittenPrototype())
- FT = dyn_cast<FunctionProtoType>(AFT);
- FD->printQualifiedName(POut, Policy);
- return std::string(POut.str());
- }
- }
if (IK == PredefinedExpr::FuncDName) {
if (const NamedDecl *ND = dyn_cast<NamedDecl>(CurrentDecl)) {
std::unique_ptr<MangleContext> MC;
@@ -792,18 +772,21 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
return std::string(Out.str());
}
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
- if (IK != PrettyFunction && IK != PrettyFunctionNoVirtual &&
- IK != FuncSig && IK != LFuncSig)
+ const auto &LO = Context.getLangOpts();
+ if (((IK == Func || IK == Function) && !LO.MicrosoftExt) ||
+ (IK == LFunction && LO.MicrosoftExt))
return FD->getNameAsString();
SmallString<256> Name;
llvm::raw_svector_ostream Out(Name);
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
- if (MD->isVirtual() && IK != PrettyFunctionNoVirtual)
- Out << "virtual ";
- if (MD->isStatic())
- Out << "static ";
+ if (IK != Function) {
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ if (MD->isVirtual() && IK != PrettyFunctionNoVirtual)
+ Out << "virtual ";
+ if (MD->isStatic())
+ Out << "static ";
+ }
}
class PrettyCallbacks final : public PrintingCallbacks {
@@ -818,9 +801,10 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
private:
const LangOptions &LO;
};
- PrintingPolicy Policy(Context.getLangOpts());
- PrettyCallbacks PrettyCB(Context.getLangOpts());
+ PrintingPolicy Policy(LO);
+ PrettyCallbacks PrettyCB(LO);
Policy.Callbacks = &PrettyCB;
+ Policy.MSVCFormatting = LO.MicrosoftExt;
std::string Proto;
llvm::raw_string_ostream POut(Proto);
@@ -847,6 +831,11 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
FD->printQualifiedName(POut, Policy);
+ if ((IK == Function || IK == Func) && LO.MicrosoftExt) {
+ 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 e4abf4b2160682a..589c4e03e329e7e 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -2218,8 +2218,8 @@ printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,
} else {
if (!FirstArg)
OS << Comma;
- //if (Argument.getKind() == TemplateArgument::Type)
- // OS << "class ";
+ if (Policy.MSVCFormatting && Argument.getKind() == TemplateArgument::Type)
+ OS << "class ";
// Tries to print the argument with location info if exists.
printArgument(Arg, Policy, ArgOS,
diff --git a/clang/test/CodeGenCXX/predefined-expr.cpp b/clang/test/CodeGenCXX/predefined-expr.cpp
index 815bcbb3bd8992f..af76e0538a9ec9f 100644
--- a/clang/test/CodeGenCXX/predefined-expr.cpp
+++ b/clang/test/CodeGenCXX/predefined-expr.cpp
@@ -5,6 +5,8 @@
// 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"
@@ -101,6 +103,7 @@
int printf(const char * _Format, ...);
+int strcmp(const char *, const char *);
class ClassInTopLevelNamespace {
public:
@@ -455,6 +458,21 @@ 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();
@@ -535,6 +553,7 @@ 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 e92fb35b653a8f3..d4d4c8fa650e1af 100644
--- a/clang/test/SemaCXX/source_location.cpp
+++ b/clang/test/SemaCXX/source_location.cpp
@@ -649,8 +649,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.func, "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;
}
@@ -677,7 +685,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 {
More information about the cfe-commits
mailing list