Skip to content

[clang-cl] Fix value of __FUNCTION__ and __FUNC__ in MSVC mode for c++. #66120

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

Merged
merged 11 commits into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions clang/include/clang/AST/PrettyPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ struct PrintingPolicy {
SuppressImplicitBase(false), FullyQualifiedName(false),
PrintCanonicalTypes(false), PrintInjectedClassNameWithArguments(true),
UsePreferredNames(true), AlwaysIncludeTypeForTemplateArgument(false),
CleanUglifiedParameters(false), EntireContentsOfLargeArray(true),
UseEnumerators(true) {}
UseClassForTemplateArgument(false), CleanUglifiedParameters(false),
EntireContentsOfLargeArray(true), UseEnumerators(true) {}

/// Adjust this printing policy for cases where it's known that we're
/// printing C++ code (for instance, if AST dumping reaches a C++-only
Expand Down Expand Up @@ -291,6 +291,10 @@ struct PrintingPolicy {
/// parameters.
unsigned AlwaysIncludeTypeForTemplateArgument : 1;

// Prints "class" keyword before type template arguments. This is used when
// printing a function via the _FUNCTION__ or __func__ macro in MSVC mode.
unsigned UseClassForTemplateArgument : 1;

/// Whether to strip underscores when printing reserved parameter names.
/// e.g. std::vector<class _Tp> becomes std::vector<class Tp>.
/// This only affects parameter names, and so describes a compatible API.
Expand Down
27 changes: 18 additions & 9 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -772,18 +772,21 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
return std::string(Out.str());
}
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
if (IK != PrettyFunction && IK != PrettyFunctionNoVirtual &&
IK != FuncSig && IK != LFuncSig)
const auto &LO = Context.getLangOpts();
if (((IK == Func || IK == Function) && !LO.MicrosoftExt) ||
(IK == LFunction && LO.MicrosoftExt))
return FD->getNameAsString();

SmallString<256> Name;
llvm::raw_svector_ostream Out(Name);

if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
if (MD->isVirtual() && IK != PrettyFunctionNoVirtual)
Out << "virtual ";
if (MD->isStatic())
Out << "static ";
if (IK != Function) {
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
if (MD->isVirtual() && IK != PrettyFunctionNoVirtual)
Out << "virtual ";
if (MD->isStatic())
Out << "static ";
}
}

class PrettyCallbacks final : public PrintingCallbacks {
Expand All @@ -798,9 +801,10 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
private:
const LangOptions &LO;
};
PrintingPolicy Policy(Context.getLangOpts());
PrettyCallbacks PrettyCB(Context.getLangOpts());
PrintingPolicy Policy(LO);
PrettyCallbacks PrettyCB(LO);
Policy.Callbacks = &PrettyCB;
Policy.UseClassForTemplateArgument = LO.MicrosoftExt;
std::string Proto;
llvm::raw_string_ostream POut(Proto);

Expand All @@ -827,6 +831,11 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {

FD->printQualifiedName(POut, Policy);

if ((IK == Function || IK == Func) && LO.MicrosoftExt) {
Out << Proto;
return std::string(Name);
}

POut << "(";
if (FT) {
for (unsigned i = 0, e = Decl->getNumParams(); i != e; ++i) {
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/AST/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2218,6 +2218,10 @@ printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,
} else {
if (!FirstArg)
OS << Comma;
if (Policy.UseClassForTemplateArgument &&
Argument.getKind() == TemplateArgument::Type)
OS << "class ";

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: if we go with this solution, this needs to happen here, but it should be under some conditions?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would move it into printArgument. If you have to, it would be find to add a new flag to PrintingPolicy. We have lots of fine-grained flags there.

// Tries to print the argument with location info if exists.
printArgument(Arg, Policy, ArgOS,
TemplateParameterList::shouldIncludeTypeForArgument(
Expand Down
10 changes: 5 additions & 5 deletions clang/test/AST/Interp/literals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1046,8 +1046,8 @@ 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(__func__, "foo"), "");
static_assert(strings_match(__FUNCTION__, "PredefinedExprs::foo"), "");
static_assert(strings_match(__func__, "PredefinedExprs::foo"), "");
static_assert(strings_match(__PRETTY_FUNCTION__, "void PredefinedExprs::foo()"), "");
}

Expand All @@ -1058,9 +1058,9 @@ namespace PredefinedExprs {
// expected-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
}

Expand Down
22 changes: 16 additions & 6 deletions clang/test/Analysis/eval-predefined-exprs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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::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__);
Expand All @@ -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::~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__);
Expand Down
19 changes: 19 additions & 0 deletions clang/test/CodeGenCXX/predefined-expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
// CHECK-DAG: private unnamed_addr constant [49 x i8] c"void functionTemplateExplicitSpecialization(int)\00"

// CHECK-DAG: private unnamed_addr constant [95 x i8] c"void SpecializedClassTemplate<char>::memberFunctionTemplate(T, U) const [T = char, U = double]\00"
// CHECK-DAG: private unnamed_addr constant [43 x i8] c"TestClass<class UnitTestNative>::TestClass\00"
// CHECK-DAG: private unnamed_addr constant [10 x i8] c"TestClass\00"
// CHECK-DAG: private unnamed_addr constant [85 x i8] c"void SpecializedClassTemplate<int>::memberFunctionTemplate(int, U) const [U = float]\00"
// CHECK-DAG: private unnamed_addr constant [57 x i8] c"void NonTypeTemplateParam<42>::size() const [Count = 42]\00"
// CHECK-DAG: private unnamed_addr constant [103 x i8] c"static void ClassWithTemplateTemplateParam<char>::staticMember() [T = char, Param = NS::ClassTemplate]\00"
Expand Down Expand Up @@ -101,6 +103,7 @@


int printf(const char * _Format, ...);
int strcmp(const char *, const char *);

class ClassInTopLevelNamespace {
public:
Expand Down Expand Up @@ -455,6 +458,21 @@ class SpecializedClassTemplate<int>
}
};


template <class T>
class TestClass {
public:
TestClass() {
const char* expected = "TestClass<class UnitTestNative>::TestClass";
if (strcmp(expected,__FUNCTION__)==0)
printf("PASSED\n");
else
printf("FAILED %s\n",__FUNCTION__);
}
};

class UnitTestNative {};

int main() {
ClassInAnonymousNamespace anonymousNamespace;
anonymousNamespace.anonymousNamespaceFunction();
Expand Down Expand Up @@ -535,6 +553,7 @@ int main() {
SpecializedClassTemplate<char> sct2;
sct2.memberFunctionTemplate('0', 0.0);

TestClass<UnitTestNative> t;
return 0;
}

Expand Down
12 changes: 12 additions & 0 deletions clang/test/SemaCXX/source_location.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -649,8 +649,16 @@ constexpr bool test_in_func() {
static_assert(is_equal(b.a.f, "test_func_passed.cpp"));
static_assert(is_equal(b.a.f2, "test_func_passed.cpp"));
static_assert(is_equal(b.a.info.file(), "test_func_passed.cpp"));
#ifdef MS
static_assert(is_equal(b.a.func, "test_out_of_line_init::test_in_func"));
#else
static_assert(is_equal(b.a.func, "test_in_func"));
#endif
#ifdef MS
static_assert(is_equal(b.a.func, "test_out_of_line_init::test_in_func"));
#else
static_assert(is_equal(b.a.func2, "test_in_func"));
#endif
static_assert(is_equal(b.a.info.function(), "bool test_out_of_line_init::test_in_func()"));
return true;
}
Expand All @@ -677,7 +685,11 @@ constexpr InInit II;

static_assert(II.l == 5200, "");
static_assert(is_equal(II.f, "in_init.cpp"));
#ifdef MS
static_assert(is_equal(II.func, "test_global_scope::InInit::InInit"));
#else
static_assert(is_equal(II.func, "InInit"));
#endif

#line 5400
struct AggInit {
Expand Down