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.ammarguel...@intel.com> Date: Tue, 5 Mar 2024 05:35:16 -0800 Subject: [PATCH 1/7] [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@-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();", >From 13f46938be7deaf0ae0409e374694b61e2ffe86d Mon Sep 17 00:00:00 2001 From: Zahira Ammarguellat <zahira.ammarguel...@intel.com> Date: Tue, 5 Mar 2024 14:18:39 -0800 Subject: [PATCH 2/7] 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@-4 {{&Element{"A",0 S64b,char}}} - // expected-warning@-4 {{&Element{"A::A",0 S64b,char}}} + clang_analyzer_dump(__func__); // expected-warning {{&Element{"A",0 S64b,char}}} #else - // expected-warning@-7 {{&Element{"A",0 S64b,char}}} - // expected-warning@-7 {{&Element{"A",0 S64b,char}}} + clang_analyzer_dump(__func__); // expected-warning {{&Element{"A",0 S64b,char}}} #endif - // expected-warning@-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@-4 {{&Element{"~A",0 S64b,char}}} - // expected-warning@-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@-7 {{&Element{"~A",0 S64b,char}}} - // expected-warning@-7 {{&Element{"~A",0 S64b,char}}} + clang_analyzer_dump(__FUNCTION__); // expected-warning {{&Element{"~A",0 S64b,char}}} #endif - // expected-warning@-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.ammarguel...@intel.com> Date: Wed, 6 Mar 2024 04:41:05 -0800 Subject: [PATCH 3/7] 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.ammarguel...@intel.com> Date: Wed, 6 Mar 2024 05:13:32 -0800 Subject: [PATCH 4/7] 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.ammarguel...@intel.com> Date: Wed, 6 Mar 2024 06:32:33 -0800 Subject: [PATCH 5/7] 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.ammarguel...@intel.com> Date: Thu, 14 Mar 2024 06:15:14 -0700 Subject: [PATCH 6/7] 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.ammarguel...@intel.com> Date: Thu, 14 Mar 2024 07:34:52 -0700 Subject: [PATCH 7/7] 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) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits