[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