-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang-cl] Fix value of __FUNCTION__ in MSVC mode. #84014
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
I’m not entirely sure this change is a good idea: some people might be relying on Clang’s behaviour wrt |
Thanks for the review. This is an issue that we encountered in our internal testing with an application using |
@llvm/pr-subscribers-clang Author: Zahira Ammarguellat (zahiraam) ChangesPredefined macro FUNCTION in clang is not returning the same string than MS for templated functions. See https://godbolt.org/z/q3EKn5zq4 For the same test case MSVC is returning: function: TestClass::TestClass Full diff: https://github.com/llvm/llvm-project/pull/84014.diff 9 Files Affected:
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@-3 {{&Element{"A",0 S64b,char}}}
- // expected-warning@-3 {{&Element{"A",0 S64b,char}}}
- // expected-warning@-3 {{&Element{"A::A()",0 S64b,char}}}
+#ifdef ANALYZER_MS
+ // expected-warning@-4 {{&Element{"A",0 S64b,char}}}
+ // expected-warning@-4 {{&Element{"A::A",0 S64b,char}}}
+#else
+ // expected-warning@-7 {{&Element{"A",0 S64b,char}}}
+ // expected-warning@-7 {{&Element{"A",0 S64b,char}}}
+#endif
+ // expected-warning@-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@-3 {{&Element{"~A",0 S64b,char}}}
- // expected-warning@-3 {{&Element{"~A",0 S64b,char}}}
- // expected-warning@-3 {{&Element{"A::~A()",0 S64b,char}}}
+#ifdef ANALYZER_MS
+ // expected-warning@-4 {{&Element{"~A",0 S64b,char}}}
+ // expected-warning@-4 {{&Element{"A::~A",0 S64b,char}}}
+#else
+ // expected-warning@-7 {{&Element{"~A",0 S64b,char}}}
+ // expected-warning@-7 {{&Element{"~A",0 S64b,char}}}
+#endif
+ // expected-warning@-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();",
|
Oh, I just noticed that you’ve tried to land this change before (#66120), but it seems it was reverted because of some problems; if those are fixed now, then I’d say going forward with this is probably fine, seeing as it was approved the first time round. This would have been a bit less confusing if you had pointed that out, just saying ;Þ |
Yes. Sorry about that. This patch was mostly to fix the issues raised in PR#66120. |
Alright, the changes look sensible to me, but I’d like for someone who’s more familiar with this part of Clang or with the original pr to comment on them too before we merge it. |
clang/docs/ReleaseNotes.rst
Outdated
@@ -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__`` in MSVC compatibility mode. | |||
Fixes (GH#66114). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixes (GH#66114). | |
Fixes (#GH66114). |
clang/lib/AST/Expr.cpp
Outdated
bool isFuncOrFunctionInNonMSVCCompatEnv = | ||
((IK == PredefinedIdentKind::Func || | ||
IK == PredefinedIdentKind ::Function) && | ||
!LO.MSVCCompat); | ||
bool isLFunctionInMSVCCommpatEnv = | ||
IK == PredefinedIdentKind::LFunction && LO.MSVCCompat; | ||
bool isFuncOrFunctionOrLFunctionOrFuncDName = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bool isFuncOrFunctionInNonMSVCCompatEnv = | |
((IK == PredefinedIdentKind::Func || | |
IK == PredefinedIdentKind ::Function) && | |
!LO.MSVCCompat); | |
bool isLFunctionInMSVCCommpatEnv = | |
IK == PredefinedIdentKind::LFunction && LO.MSVCCompat; | |
bool isFuncOrFunctionOrLFunctionOrFuncDName = | |
bool IsFuncOrFunctionInNonMSVCCompatEnv = | |
((IK == PredefinedIdentKind::Func || | |
IK == PredefinedIdentKind ::Function) && | |
!LO.MSVCCompat); | |
bool IsLFunctionInMSVCCommpatEnv = | |
IK == PredefinedIdentKind::LFunction && LO.MSVCCompat; | |
bool IsFuncOrFunctionOrLFunctionOrFuncDName = |
Coding style nits, NFC
clang/lib/AST/Expr.cpp
Outdated
IK != PredefinedIdentKind::LFuncSig; | ||
if ((ForceElaboratedPrinting && | ||
(isFuncOrFunctionInNonMSVCCompatEnv || isLFunctionInMSVCCommpatEnv)) || | ||
!ForceElaboratedPrinting && isFuncOrFunctionOrLFunctionOrFuncDName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!ForceElaboratedPrinting && isFuncOrFunctionOrLFunctionOrFuncDName) | |
(!ForceElaboratedPrinting && isFuncOrFunctionOrLFunctionOrFuncDName)) |
You may need this to avoid diagnostics about mixed &&
and ||
operators.
Policy.SuppressTagKeyword = true; | ||
Policy.SuppressScope = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we want to reset these once we're done with the call to printBefore()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, your changes don't look quite right to me. The return printBefore(...);
is going to skip right over the restoration.
I think you wanted something more like:
bool OldTag = Policy.SuppressTagKeyword, OldScope = Policy.SuppressScope;
Policy.SuppressTagKeyword = true;
Policy.SuppressScope = false;
printBefore(T->getNamedType(), OS);
Policy.SuppressTagKeyword = OldTag;
Policy.SuppressScope = OldScope;
return;
Before making the changes, I think you should also add test coverage to the unit test where these changes will fix the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you mean here "where these changes will fix the test"? will fix which test? The unit test you are referring to is DeclPrinterTest
? this should be TestCXXRecordDecl12
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code was broken but no tests failed, then the fix you made was also broken but still no tests failed. So I'm asking you to write a new test that demonstrates incorrect behavior related to failing to reset the printing policy after modifying it, then fix the code until that test shows the correct behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm! Can't seem to find a test case that fails. At each step of the printing ElaboratedTypePolicyRAII PolicyRAII(Policy);
gets called and that re-initializes the values of Policy.SuppressTagKeyword
and Policy.SuppressScope
to true!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to reset the values here, or use a separate PrintingPolicy
object so that you're not changing the value for the default printing policy used.
✅ With the latest revision this PR passed the C/C++ code formatter. |
From what I can tell, it seems that Aaron is a lot more familiar w/ this part of Clang than me, so I’ll leave it to him to comment on whether these changes make sense. |
clang/lib/AST/DeclPrinter.cpp
Outdated
@@ -679,6 +679,19 @@ static void printExplicitSpecifier(ExplicitSpecifier ES, llvm::raw_ostream &Out, | |||
Out << Proto; | |||
} | |||
|
|||
static void AddPrefix(PrintingPolicy &Policy, QualType T, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a pretty non-descriptive function name; the caller will have no idea what kind of prefix it adds. But trying to come up with a name for this is... not easy.
MaybePrintTagKeywordIfSupressingScopes
is not super great either. :-D
clang/lib/AST/DeclPrinter.cpp
Outdated
StringRef prefix; | ||
prefix = T->isClassType() ? "class " | ||
: T->isStructureType() ? "struct " | ||
: T->isUnionType() ? "union " | ||
: ""; | ||
Out << prefix; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
StringRef prefix; | |
prefix = T->isClassType() ? "class " | |
: T->isStructureType() ? "struct " | |
: T->isUnionType() ? "union " | |
: ""; | |
Out << prefix; | |
StringRef prefix = T->isClassType() ? "class " | |
: T->isStructureType() ? "struct " | |
: T->isUnionType() ? "union " | |
: ""; | |
Out << prefix; |
And probably needs to be reformatted.
clang/lib/AST/DeclPrinter.cpp
Outdated
if (!Policy.SuppressTagKeyword && Policy.SuppressScope && | ||
!Policy.SuppressUnwrittenScope) { | ||
AddPrefix(Policy, AFT->getReturnType(), Out); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check is duplicated in AddPrefix()
, same below (probably can remove the check from AddPrefix()
or turn it into an assertion).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed it from MaybePrintTagKeywordIfSupressingScopes
.
clang/lib/AST/DeclPrinter.cpp
Outdated
bool OldTagKeyword = Policy.SuppressTagKeyword; | ||
bool OldSupressScope = Policy.SuppressScope; | ||
AFT->getReturnType().print(Out, Policy, Proto); | ||
Policy.SuppressTagKeyword = OldTagKeyword; | ||
Policy.SuppressScope = OldSupressScope; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is only necessary because of the changes you made in TypePrinter.cpp, right? e.g., if we reset the policy back to its original values there, we don't need to do it here.
clang/lib/AST/DeclPrinter.cpp
Outdated
bool OldTagKeyword = Policy.SuppressTagKeyword; | ||
bool OldSupressScope = Policy.SuppressScope; | ||
printDeclType(T, Name); | ||
Policy.SuppressTagKeyword = OldTagKeyword; | ||
Policy.SuppressScope = OldSupressScope; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
Policy.SuppressTagKeyword = true; | ||
Policy.SuppressScope = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to reset the values here, or use a separate PrintingPolicy
object so that you're not changing the value for the default printing policy used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I spotted some simplifications that can be applied. If precommit CI comes back green, then I think this is basically ready to go.
clang/lib/AST/DeclPrinter.cpp
Outdated
if (!Policy.SuppressTagKeyword && Policy.SuppressScope && | ||
!Policy.SuppressUnwrittenScope) { | ||
MaybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(), | ||
Out); | ||
AFT->getReturnType().print(Out, Policy, Proto); | ||
} else { | ||
AFT->getReturnType().print(Out, Policy, Proto); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (!Policy.SuppressTagKeyword && Policy.SuppressScope && | |
!Policy.SuppressUnwrittenScope) { | |
MaybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(), | |
Out); | |
AFT->getReturnType().print(Out, Policy, Proto); | |
} else { | |
AFT->getReturnType().print(Out, Policy, Proto); | |
} | |
if (!Policy.SuppressTagKeyword && Policy.SuppressScope && | |
!Policy.SuppressUnwrittenScope) | |
MaybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(), | |
Out); | |
AFT->getReturnType().print(Out, Policy, Proto); |
if (!Policy.SuppressTagKeyword && Policy.SuppressScope && | ||
!Policy.SuppressUnwrittenScope) { | ||
MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out); | ||
printDeclType(T, Name); | ||
} else { | ||
printDeclType(T, Name); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (!Policy.SuppressTagKeyword && Policy.SuppressScope && | |
!Policy.SuppressUnwrittenScope) { | |
MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out); | |
printDeclType(T, Name); | |
} else { | |
printDeclType(T, Name); | |
} | |
if (!Policy.SuppressTagKeyword && Policy.SuppressScope && | |
!Policy.SuppressUnwrittenScope) | |
MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out); | |
printDeclType(T, Name); |
Thank you all for the reviews. |
Predefined macro FUNCTION in clang is not returning the same string than MS for templated functions. See https://godbolt.org/z/q3EKn5zq4 For the same test case MSVC is returning: function: TestClass::TestClass function: TestStruct::TestStruct function: TestEnum::TestEnum The initial work for this was in the reverted patch (llvm#66120). This patch solves the issues raised in the reverted patch.
An upcoming LLVM change (llvm/llvm-project#84014) will make it so that the __FUNCTION__ macro will expand to the fully qulified name of class/struct methods instead of only the method name itself. That change is consistent with what MSVC does. To fix this, we fix BeforeStateCheckAction(...) so that it checks that the substring "Check" is present anywhere in the function name rather than specifically at the beginning of the function name. Bug: 331665490 Fixed: 331665490 Change-Id: Id7bce021d9b18b7db1805f37fbc08a6fc0bb3647 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5402860 Auto-Submit: Alan Zhao <[email protected]> Commit-Queue: Alan Zhao <[email protected]> Reviewed-by: Mike Wasserman <[email protected]> Cr-Commit-Position: refs/heads/main@{#1279841}
Predefined macro FUNCTION in clang is not returning the same string than MS for templated functions.
See https://godbolt.org/z/q3EKn5zq4
For the same test case MSVC is returning:
function: TestClass::TestClass
function: TestStruct::TestStruct
function: TestEnum::TestEnum
The initial work for this was in the reverted patch (#66120). This patch solves the issues raised in the reverted patch.