[clang] [clang-cl] Fix value of __FUNCTION__ in MSVC mode. (PR #84014)
Zahira Ammarguellat via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 19 03:56:37 PDT 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 01/10] [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 02/10] 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 03/10] 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 04/10] 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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>From 463cbc9d24c3ec5e020802603c97d32d5b1246cc Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Wed, 6 Mar 2024 06:32:33 -0800
Subject: [PATCH 05/10] Addressed review comment.
---
clang/lib/AST/Expr.cpp | 10 +++++-----
clang/lib/AST/TypePrinter.cpp | 6 ++++++
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index c2524b2df0fe2a..39fcad88a9a6a7 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -723,20 +723,20 @@ std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK,
}
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
const auto &LO = Context.getLangOpts();
- bool isFuncOrFunctionInNonMSVCCompatEnv =
+ bool IsFuncOrFunctionInNonMSVCCompatEnv =
((IK == PredefinedIdentKind::Func ||
IK == PredefinedIdentKind ::Function) &&
!LO.MSVCCompat);
- bool isLFunctionInMSVCCommpatEnv =
+ bool IsLFunctionInMSVCCommpatEnv =
IK == PredefinedIdentKind::LFunction && LO.MSVCCompat;
- bool isFuncOrFunctionOrLFunctionOrFuncDName =
+ bool IsFuncOrFunctionOrLFunctionOrFuncDName =
IK != PredefinedIdentKind::PrettyFunction &&
IK != PredefinedIdentKind::PrettyFunctionNoVirtual &&
IK != PredefinedIdentKind::FuncSig &&
IK != PredefinedIdentKind::LFuncSig;
if ((ForceElaboratedPrinting &&
- (isFuncOrFunctionInNonMSVCCompatEnv || isLFunctionInMSVCCommpatEnv)) ||
- !ForceElaboratedPrinting && isFuncOrFunctionOrLFunctionOrFuncDName)
+ (IsFuncOrFunctionInNonMSVCCompatEnv || IsLFunctionInMSVCCommpatEnv)) ||
+ (!ForceElaboratedPrinting && IsFuncOrFunctionOrLFunctionOrFuncDName))
return FD->getNameAsString();
SmallString<256> Name;
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 6de90638d916cf..833bd964995780 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1628,6 +1628,7 @@ void TypePrinter::printElaboratedBefore(const ElaboratedType *T,
return;
}
+ bool ResetPolicy = false;
// The tag definition will take care of these.
if (!Policy.IncludeTagDefinition)
{
@@ -1637,6 +1638,7 @@ void TypePrinter::printElaboratedBefore(const ElaboratedType *T,
NestedNameSpecifier *Qualifier = T->getQualifier();
if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
!Policy.SuppressUnwrittenScope) {
+ ResetPolicy = true;
StringRef prefix = T->isClassType() ? "class "
: T->isStructureType() ? "struct "
: T->isUnionType() ? "union "
@@ -1652,6 +1654,10 @@ void TypePrinter::printElaboratedBefore(const ElaboratedType *T,
ElaboratedTypePolicyRAII PolicyRAII(Policy);
printBefore(T->getNamedType(), OS);
+ if (ResetPolicy) {
+ Policy.SuppressTagKeyword = false;
+ Policy.SuppressScope = true;
+ }
}
void TypePrinter::printElaboratedAfter(const ElaboratedType *T,
>From 4b42f76d5c1e5439311cc8153ef9530be2625840 Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Thu, 14 Mar 2024 06:15:14 -0700
Subject: [PATCH 06/10] Refactor the code and added entry to
TypePrinterTest.cpp.
---
clang/lib/AST/DeclPrinter.cpp | 37 ++++++++++++++++++++--
clang/lib/AST/TypePrinter.cpp | 14 ++-------
clang/unittests/AST/DeclPrinterTest.cpp | 41 +++++++++++++++++++++++++
clang/unittests/AST/TypePrinterTest.cpp | 18 +++++++++++
4 files changed, 96 insertions(+), 14 deletions(-)
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 43d221968ea3fb..af736fa46a165a 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -679,6 +679,19 @@ static void printExplicitSpecifier(ExplicitSpecifier ES, llvm::raw_ostream &Out,
Out << Proto;
}
+static void AddPrefix(PrintingPolicy &Policy, QualType T,
+ llvm::raw_ostream &Out) {
+ if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
+ !Policy.SuppressUnwrittenScope) {
+ StringRef prefix;
+ prefix = T->isClassType() ? "class "
+ : T->isStructureType() ? "struct "
+ : T->isUnionType() ? "union "
+ : "";
+ Out << prefix;
+ }
+}
+
void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
if (!D->getDescribedFunctionTemplate() &&
!D->isFunctionTemplateSpecialization())
@@ -855,7 +868,17 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
Out << Proto << " -> ";
Proto.clear();
}
- AFT->getReturnType().print(Out, Policy, Proto);
+ if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
+ !Policy.SuppressUnwrittenScope) {
+ AddPrefix(Policy, AFT->getReturnType(), Out);
+ bool OldTagKeyword = Policy.SuppressTagKeyword;
+ bool OldSupressScope = Policy.SuppressScope;
+ AFT->getReturnType().print(Out, Policy, Proto);
+ Policy.SuppressTagKeyword = OldTagKeyword;
+ Policy.SuppressScope = OldSupressScope;
+ } else {
+ AFT->getReturnType().print(Out, Policy, Proto);
+ }
Proto.clear();
}
Out << Proto;
@@ -1022,7 +1045,17 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
? D->getIdentifier()->deuglifiedName()
: D->getName();
- printDeclType(T, Name);
+ if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
+ !Policy.SuppressUnwrittenScope) {
+ AddPrefix(Policy, T, Out);
+ bool OldTagKeyword = Policy.SuppressTagKeyword;
+ bool OldSupressScope = Policy.SuppressScope;
+ printDeclType(T, Name);
+ Policy.SuppressTagKeyword = OldTagKeyword;
+ Policy.SuppressScope = OldSupressScope;
+ } else {
+ printDeclType(T, Name);
+ }
// Print the attributes that should be placed right before the end of the
// decl.
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 833bd964995780..e43acc44118892 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1628,7 +1628,6 @@ void TypePrinter::printElaboratedBefore(const ElaboratedType *T,
return;
}
- bool ResetPolicy = false;
// The tag definition will take care of these.
if (!Policy.IncludeTagDefinition)
{
@@ -1638,15 +1637,10 @@ void TypePrinter::printElaboratedBefore(const ElaboratedType *T,
NestedNameSpecifier *Qualifier = T->getQualifier();
if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
!Policy.SuppressUnwrittenScope) {
- ResetPolicy = true;
- StringRef prefix = T->isClassType() ? "class "
- : T->isStructureType() ? "struct "
- : T->isUnionType() ? "union "
- : "";
- OS << prefix;
Policy.SuppressTagKeyword = true;
Policy.SuppressScope = false;
- return printBefore(T->getNamedType(), OS);
+ printBefore(T->getNamedType(), OS);
+ return;
}
if (Qualifier)
Qualifier->print(OS, Policy);
@@ -1654,10 +1648,6 @@ void TypePrinter::printElaboratedBefore(const ElaboratedType *T,
ElaboratedTypePolicyRAII PolicyRAII(Policy);
printBefore(T->getNamedType(), OS);
- if (ResetPolicy) {
- Policy.SuppressTagKeyword = false;
- Policy.SuppressScope = true;
- }
}
void TypePrinter::printElaboratedAfter(const ElaboratedType *T,
diff --git a/clang/unittests/AST/DeclPrinterTest.cpp b/clang/unittests/AST/DeclPrinterTest.cpp
index 8fcfaa7c2f0379..06829313b57ad9 100644
--- a/clang/unittests/AST/DeclPrinterTest.cpp
+++ b/clang/unittests/AST/DeclPrinterTest.cpp
@@ -359,6 +359,47 @@ TEST(DeclPrinter, TestCXXRecordDecl11) {
}
TEST(DeclPrinter, TestCXXRecordDecl12) {
+ ASSERT_TRUE(PrintedDeclCXX98Matches(
+ "struct S { int x; };"
+ "namespace NS { class C {};}"
+ "void foo() {using namespace NS; C c;}",
+ "foo",
+ "void foo() {\nusing namespace NS;\nclass "
+ "NS::C c;\n}\n",
+ [](PrintingPolicy &Policy) {
+ Policy.SuppressTagKeyword = false;
+ Policy.SuppressScope = true;
+ Policy.TerseOutput = false;
+ }));
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl13) {
+ ASSERT_TRUE(PrintedDeclCXX98Matches(
+ "struct S { int x; };"
+ "S s1;"
+ "S foo() {return s1;}",
+ "foo",
+ "struct S foo() {\nreturn s1;\n}\n",
+ [](PrintingPolicy &Policy) {
+ Policy.SuppressTagKeyword = false;
+ Policy.SuppressScope = true;
+ Policy.TerseOutput = false;
+ }));
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl14) {
+ ASSERT_TRUE(PrintedDeclCXX98Matches(
+ "struct S { int x; };"
+ "S foo(S s1) {return s1;}",
+ "foo",
+ "struct S foo(struct S s1) {\nreturn s1;\n}\n",
+ [](PrintingPolicy &Policy) {
+ Policy.SuppressTagKeyword = false;
+ Policy.SuppressScope = true;
+ Policy.TerseOutput = false;
+ }));
+}
+TEST(DeclPrinter, TestCXXRecordDecl15) {
ASSERT_TRUE(PrintedDeclCXX98Matches(
"struct S { int x; };"
"namespace NS { class C {};}"
diff --git a/clang/unittests/AST/TypePrinterTest.cpp b/clang/unittests/AST/TypePrinterTest.cpp
index f0a6eb7e9fd8c9..2cdab5d1d36ab3 100644
--- a/clang/unittests/AST/TypePrinterTest.cpp
+++ b/clang/unittests/AST/TypePrinterTest.cpp
@@ -155,6 +155,24 @@ TEST(TypePrinter, TemplateIdWithNTTP) {
}));
}
+TEST(TypePrinter, TemplateArgumentsSubstitution) {
+ constexpr char Code[] = R"cpp(
+ template <typename Y> class X {};
+ typedef X<int> A;
+ int foo() {
+ return sizeof(A);
+ }
+ )cpp";
+ auto Matcher = typedefNameDecl(hasName("A"),
+ hasType(qualType().bind("id")));
+ ASSERT_TRUE(PrintedTypeMatches(
+ Code, {}, Matcher, "X<int>",
+ [](PrintingPolicy &Policy) {
+ Policy.SuppressTagKeyword = false;
+ Policy.SuppressScope = true;
+ }));
+}
+
TEST(TypePrinter, TemplateArgumentsSubstitution_Expressions) {
/// Tests clang::isSubstitutedDefaultArgument on TemplateArguments
/// that are of kind TemplateArgument::Expression
>From 878b1792a9a2cea970f6052f6f7cf35fe2840f6f Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Thu, 14 Mar 2024 07:34:52 -0700
Subject: [PATCH 07/10] Fix format.
---
clang/unittests/AST/DeclPrinterTest.cpp | 31 +++++++++++--------------
clang/unittests/AST/TypePrinterTest.cpp | 16 ++++++-------
2 files changed, 21 insertions(+), 26 deletions(-)
diff --git a/clang/unittests/AST/DeclPrinterTest.cpp b/clang/unittests/AST/DeclPrinterTest.cpp
index 06829313b57ad9..e024c41e03b484 100644
--- a/clang/unittests/AST/DeclPrinterTest.cpp
+++ b/clang/unittests/AST/DeclPrinterTest.cpp
@@ -359,18 +359,18 @@ TEST(DeclPrinter, TestCXXRecordDecl11) {
}
TEST(DeclPrinter, TestCXXRecordDecl12) {
- ASSERT_TRUE(PrintedDeclCXX98Matches(
- "struct S { int x; };"
- "namespace NS { class C {};}"
- "void foo() {using namespace NS; C c;}",
- "foo",
- "void foo() {\nusing namespace NS;\nclass "
- "NS::C c;\n}\n",
- [](PrintingPolicy &Policy) {
- Policy.SuppressTagKeyword = false;
- Policy.SuppressScope = true;
- Policy.TerseOutput = false;
- }));
+ ASSERT_TRUE(
+ PrintedDeclCXX98Matches("struct S { int x; };"
+ "namespace NS { class C {};}"
+ "void foo() {using namespace NS; C c;}",
+ "foo",
+ "void foo() {\nusing namespace NS;\nclass "
+ "NS::C c;\n}\n",
+ [](PrintingPolicy &Policy) {
+ Policy.SuppressTagKeyword = false;
+ Policy.SuppressScope = true;
+ Policy.TerseOutput = false;
+ }));
}
TEST(DeclPrinter, TestCXXRecordDecl13) {
@@ -378,9 +378,7 @@ TEST(DeclPrinter, TestCXXRecordDecl13) {
"struct S { int x; };"
"S s1;"
"S foo() {return s1;}",
- "foo",
- "struct S foo() {\nreturn s1;\n}\n",
- [](PrintingPolicy &Policy) {
+ "foo", "struct S foo() {\nreturn s1;\n}\n", [](PrintingPolicy &Policy) {
Policy.SuppressTagKeyword = false;
Policy.SuppressScope = true;
Policy.TerseOutput = false;
@@ -391,8 +389,7 @@ TEST(DeclPrinter, TestCXXRecordDecl14) {
ASSERT_TRUE(PrintedDeclCXX98Matches(
"struct S { int x; };"
"S foo(S s1) {return s1;}",
- "foo",
- "struct S foo(struct S s1) {\nreturn s1;\n}\n",
+ "foo", "struct S foo(struct S s1) {\nreturn s1;\n}\n",
[](PrintingPolicy &Policy) {
Policy.SuppressTagKeyword = false;
Policy.SuppressScope = true;
diff --git a/clang/unittests/AST/TypePrinterTest.cpp b/clang/unittests/AST/TypePrinterTest.cpp
index 2cdab5d1d36ab3..600088312b29c0 100644
--- a/clang/unittests/AST/TypePrinterTest.cpp
+++ b/clang/unittests/AST/TypePrinterTest.cpp
@@ -156,21 +156,19 @@ TEST(TypePrinter, TemplateIdWithNTTP) {
}
TEST(TypePrinter, TemplateArgumentsSubstitution) {
- constexpr char Code[] = R"cpp(
+ constexpr char Code[] = R"cpp(
template <typename Y> class X {};
typedef X<int> A;
int foo() {
return sizeof(A);
}
)cpp";
- auto Matcher = typedefNameDecl(hasName("A"),
- hasType(qualType().bind("id")));
- ASSERT_TRUE(PrintedTypeMatches(
- Code, {}, Matcher, "X<int>",
- [](PrintingPolicy &Policy) {
- Policy.SuppressTagKeyword = false;
- Policy.SuppressScope = true;
- }));
+ auto Matcher = typedefNameDecl(hasName("A"), hasType(qualType().bind("id")));
+ ASSERT_TRUE(PrintedTypeMatches(Code, {}, Matcher, "X<int>",
+ [](PrintingPolicy &Policy) {
+ Policy.SuppressTagKeyword = false;
+ Policy.SuppressScope = true;
+ }));
}
TEST(TypePrinter, TemplateArgumentsSubstitution_Expressions) {
>From bdcb510f7952a7c63bf07d2de43ecce15c659021 Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Thu, 14 Mar 2024 07:40:06 -0700
Subject: [PATCH 08/10] Fix format again.
---
clang/unittests/AST/TypePrinterTest.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/unittests/AST/TypePrinterTest.cpp b/clang/unittests/AST/TypePrinterTest.cpp
index 600088312b29c0..494085a2ebca6b 100644
--- a/clang/unittests/AST/TypePrinterTest.cpp
+++ b/clang/unittests/AST/TypePrinterTest.cpp
@@ -168,7 +168,7 @@ TEST(TypePrinter, TemplateArgumentsSubstitution) {
[](PrintingPolicy &Policy) {
Policy.SuppressTagKeyword = false;
Policy.SuppressScope = true;
- }));
+ }));
}
TEST(TypePrinter, TemplateArgumentsSubstitution_Expressions) {
>From efeb7b04194abf658a0bab9be4f5f006b7a63aa0 Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Mon, 18 Mar 2024 08:46:05 -0700
Subject: [PATCH 09/10] Responded review comments.
---
clang/lib/AST/DeclPrinter.cpp | 32 +++++++++++---------------------
clang/lib/AST/TypePrinter.cpp | 4 ++++
2 files changed, 15 insertions(+), 21 deletions(-)
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index af736fa46a165a..6861d35e255ba6 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -679,17 +679,14 @@ static void printExplicitSpecifier(ExplicitSpecifier ES, llvm::raw_ostream &Out,
Out << Proto;
}
-static void AddPrefix(PrintingPolicy &Policy, QualType T,
- llvm::raw_ostream &Out) {
- if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
- !Policy.SuppressUnwrittenScope) {
- StringRef prefix;
- prefix = T->isClassType() ? "class "
- : T->isStructureType() ? "struct "
- : T->isUnionType() ? "union "
- : "";
- Out << prefix;
- }
+static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy &Policy,
+ QualType T,
+ llvm::raw_ostream &Out) {
+ StringRef prefix = T->isClassType() ? "class "
+ : T->isStructureType() ? "struct "
+ : T->isUnionType() ? "union "
+ : "";
+ Out << prefix;
}
void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
@@ -870,12 +867,9 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
}
if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
!Policy.SuppressUnwrittenScope) {
- AddPrefix(Policy, AFT->getReturnType(), Out);
- bool OldTagKeyword = Policy.SuppressTagKeyword;
- bool OldSupressScope = Policy.SuppressScope;
+ MaybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),
+ Out);
AFT->getReturnType().print(Out, Policy, Proto);
- Policy.SuppressTagKeyword = OldTagKeyword;
- Policy.SuppressScope = OldSupressScope;
} else {
AFT->getReturnType().print(Out, Policy, Proto);
}
@@ -1047,12 +1041,8 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
!Policy.SuppressUnwrittenScope) {
- AddPrefix(Policy, T, Out);
- bool OldTagKeyword = Policy.SuppressTagKeyword;
- bool OldSupressScope = Policy.SuppressScope;
+ MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
printDeclType(T, Name);
- Policy.SuppressTagKeyword = OldTagKeyword;
- Policy.SuppressScope = OldSupressScope;
} else {
printDeclType(T, Name);
}
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index e43acc44118892..2a3e32bc6995db 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1637,9 +1637,13 @@ void TypePrinter::printElaboratedBefore(const ElaboratedType *T,
NestedNameSpecifier *Qualifier = T->getQualifier();
if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
!Policy.SuppressUnwrittenScope) {
+ bool OldTagKeyword = Policy.SuppressTagKeyword;
+ bool OldSupressScope = Policy.SuppressScope;
Policy.SuppressTagKeyword = true;
Policy.SuppressScope = false;
printBefore(T->getNamedType(), OS);
+ Policy.SuppressTagKeyword = OldTagKeyword;
+ Policy.SuppressScope = OldSupressScope;
return;
}
if (Qualifier)
>From 9f16b2581557a18c961a6f052bf8a315d705f74e Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Mon, 18 Mar 2024 12:09:32 -0700
Subject: [PATCH 10/10] Simplification applied.
---
clang/lib/AST/DeclPrinter.cpp | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 6861d35e255ba6..671c6bc6e16b56 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -866,13 +866,10 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
Proto.clear();
}
if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
- !Policy.SuppressUnwrittenScope) {
+ !Policy.SuppressUnwrittenScope)
MaybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),
Out);
- AFT->getReturnType().print(Out, Policy, Proto);
- } else {
- AFT->getReturnType().print(Out, Policy, Proto);
- }
+ AFT->getReturnType().print(Out, Policy, Proto);
Proto.clear();
}
Out << Proto;
More information about the cfe-commits
mailing list