Skip to content

Commit 78d8312

Browse files
JMazurkiewiczAaronBallman
authored andcommitted
[Clang][clang-cl] Implement __builtin_FUNCSIG
This patch implements __builtin_FUNCSIG intrinsic which returns the same string as __FUNCSIG__. Fixes #58951 Differential Revision: https://reviews.llvm.org/D150183
1 parent f809bf2 commit 78d8312

File tree

12 files changed

+131
-15
lines changed

12 files changed

+131
-15
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3711,7 +3711,7 @@ Source location builtins
37113711
37123712
Clang provides builtins to support C++ standard library implementation
37133713
of ``std::source_location`` as specified in C++20. With the exception
3714-
of ``__builtin_COLUMN`` and ``__builtin_FILE_NAME``,
3714+
of ``__builtin_COLUMN``, ``__builtin_FILE_NAME`` and ``__builtin_FUNCSIG``,
37153715
these builtins are also implemented by GCC.
37163716
37173717
**Syntax**:
@@ -3721,6 +3721,7 @@ these builtins are also implemented by GCC.
37213721
const char *__builtin_FILE();
37223722
const char *__builtin_FILE_NAME(); // Clang only
37233723
const char *__builtin_FUNCTION();
3724+
const char *__builtin_FUNCSIG(); // Microsoft
37243725
unsigned __builtin_LINE();
37253726
unsigned __builtin_COLUMN(); // Clang only
37263727
const std::source_location::__impl *__builtin_source_location();
@@ -3750,11 +3751,12 @@ these builtins are also implemented by GCC.
37503751
37513752
**Description**:
37523753
3753-
The builtins ``__builtin_LINE``, ``__builtin_FUNCTION``, ``__builtin_FILE`` and
3754-
``__builtin_FILE_NAME`` return the values, at the "invocation point", for
3755-
``__LINE__``, ``__FUNCTION__``, ``__FILE__`` and ``__FILE_NAME__`` respectively.
3756-
``__builtin_COLUMN`` similarly returns the column,
3757-
though there is no corresponding macro. These builtins are constant expressions.
3754+
The builtins ``__builtin_LINE``, ``__builtin_FUNCTION``, ``__builtin_FUNCSIG``,
3755+
``__builtin_FILE`` and ``__builtin_FILE_NAME`` return the values, at the
3756+
"invocation point", for ``__LINE__``, ``__FUNCTION__``, ``__FUNCSIG__``,
3757+
``__FILE__`` and ``__FILE_NAME__`` respectively. ``__builtin_COLUMN`` similarly
3758+
returns the column, though there is no corresponding macro. These builtins are
3759+
constant expressions.
37583760
37593761
When the builtins appear as part of a default function argument the invocation
37603762
point is the location of the caller. When the builtins appear as part of a

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ Non-comprehensive list of changes in this release
198198
``memcmp(&lhs, &rhs, sizeof(T)) == 0``.
199199
- Clang now ignores null directives outside of the include guard when deciding
200200
whether a file can be enabled for the multiple-include optimization.
201+
- Clang now support ``__builtin_FUNCSIG()`` which retruns the same information
202+
as the ``__FUNCSIG__`` macro (available only with ``-fms-extensions`` flag).
203+
This fixes (`#58951 <https://github.com/llvm/llvm-project/issues/58951>`_).
201204

202205
New Compiler Flags
203206
------------------

clang/include/clang/AST/Expr.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4691,14 +4691,22 @@ class VAArgExpr : public Expr {
46914691
};
46924692

46934693
/// Represents a function call to one of __builtin_LINE(), __builtin_COLUMN(),
4694-
/// __builtin_FUNCTION(), __builtin_FILE(), __builtin_FILE_NAME(),
4695-
/// or __builtin_source_location().
4694+
/// __builtin_FUNCTION(), __builtin_FUNCSIG(), __builtin_FILE(),
4695+
/// __builtin_FILE_NAME() or __builtin_source_location().
46964696
class SourceLocExpr final : public Expr {
46974697
SourceLocation BuiltinLoc, RParenLoc;
46984698
DeclContext *ParentContext;
46994699

47004700
public:
4701-
enum IdentKind { Function, File, FileName, Line, Column, SourceLocStruct };
4701+
enum IdentKind {
4702+
Function,
4703+
FuncSig,
4704+
File,
4705+
FileName,
4706+
Line,
4707+
Column,
4708+
SourceLocStruct
4709+
};
47024710

47034711
SourceLocExpr(const ASTContext &Ctx, IdentKind Type, QualType ResultTy,
47044712
SourceLocation BLoc, SourceLocation RParenLoc,
@@ -4724,6 +4732,7 @@ class SourceLocExpr final : public Expr {
47244732
case File:
47254733
case FileName:
47264734
case Function:
4735+
case FuncSig:
47274736
case SourceLocStruct:
47284737
return false;
47294738
case Line:

clang/include/clang/Basic/TokenKinds.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ KEYWORD(__builtin_offsetof , KEYALL)
438438
KEYWORD(__builtin_FILE , KEYALL)
439439
KEYWORD(__builtin_FILE_NAME , KEYALL)
440440
KEYWORD(__builtin_FUNCTION , KEYALL)
441+
KEYWORD(__builtin_FUNCSIG , KEYMS)
441442
KEYWORD(__builtin_LINE , KEYALL)
442443
KEYWORD(__builtin_COLUMN , KEYALL)
443444
KEYWORD(__builtin_source_location , KEYCXX)

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6006,8 +6006,8 @@ class Sema final {
60066006
ExprResult BuildVAArgExpr(SourceLocation BuiltinLoc, Expr *E,
60076007
TypeSourceInfo *TInfo, SourceLocation RPLoc);
60086008

6009-
// __builtin_LINE(), __builtin_FUNCTION(), __builtin_FILE(),
6010-
// __builtin_COLUMN(), __builtin_source_location()
6009+
// __builtin_LINE(), __builtin_FUNCTION(), __builtin_FUNCSIG(),
6010+
// __builtin_FILE(), __builtin_COLUMN(), __builtin_source_location()
60116011
ExprResult ActOnSourceLocExpr(SourceLocExpr::IdentKind Kind,
60126012
SourceLocation BuiltinLoc,
60136013
SourceLocation RPLoc);

clang/lib/AST/Expr.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2247,6 +2247,8 @@ StringRef SourceLocExpr::getBuiltinStr() const {
22472247
return "__builtin_FILE_NAME";
22482248
case Function:
22492249
return "__builtin_FUNCTION";
2250+
case FuncSig:
2251+
return "__builtin_FUNCSIG";
22502252
case Line:
22512253
return "__builtin_LINE";
22522254
case Column:
@@ -2297,11 +2299,14 @@ APValue SourceLocExpr::EvaluateInContext(const ASTContext &Ctx,
22972299
Ctx.getTargetInfo());
22982300
return MakeStringLiteral(Path);
22992301
}
2300-
case SourceLocExpr::Function: {
2302+
case SourceLocExpr::Function:
2303+
case SourceLocExpr::FuncSig: {
23012304
const auto *CurDecl = dyn_cast<Decl>(Context);
2305+
const auto Kind = getIdentKind() == SourceLocExpr::Function
2306+
? PredefinedExpr::Function
2307+
: PredefinedExpr::FuncSig;
23022308
return MakeStringLiteral(
2303-
CurDecl ? PredefinedExpr::ComputeName(PredefinedExpr::Function, CurDecl)
2304-
: std::string(""));
2309+
CurDecl ? PredefinedExpr::ComputeName(Kind, CurDecl) : std::string(""));
23052310
}
23062311
case SourceLocExpr::Line:
23072312
case SourceLocExpr::Column: {

clang/lib/Parse/ParseExpr.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,7 @@ class CastExpressionIdValidator final : public CorrectionCandidateCallback {
792792
/// [GNU] '__builtin_FILE' '(' ')'
793793
/// [CLANG] '__builtin_FILE_NAME' '(' ')'
794794
/// [GNU] '__builtin_FUNCTION' '(' ')'
795+
/// [MS] '__builtin_FUNCSIG' '(' ')'
795796
/// [GNU] '__builtin_LINE' '(' ')'
796797
/// [CLANG] '__builtin_COLUMN' '(' ')'
797798
/// [GNU] '__builtin_source_location' '(' ')'
@@ -1321,6 +1322,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
13211322
case tok::kw___builtin_FILE:
13221323
case tok::kw___builtin_FILE_NAME:
13231324
case tok::kw___builtin_FUNCTION:
1325+
case tok::kw___builtin_FUNCSIG:
13241326
case tok::kw___builtin_LINE:
13251327
case tok::kw___builtin_source_location:
13261328
if (NotPrimaryExpression)
@@ -2547,6 +2549,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
25472549
/// [GNU] '__builtin_FILE' '(' ')'
25482550
/// [CLANG] '__builtin_FILE_NAME' '(' ')'
25492551
/// [GNU] '__builtin_FUNCTION' '(' ')'
2552+
/// [MS] '__builtin_FUNCSIG' '(' ')'
25502553
/// [GNU] '__builtin_LINE' '(' ')'
25512554
/// [CLANG] '__builtin_COLUMN' '(' ')'
25522555
/// [GNU] '__builtin_source_location' '(' ')'
@@ -2783,6 +2786,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
27832786
case tok::kw___builtin_FILE:
27842787
case tok::kw___builtin_FILE_NAME:
27852788
case tok::kw___builtin_FUNCTION:
2789+
case tok::kw___builtin_FUNCSIG:
27862790
case tok::kw___builtin_LINE:
27872791
case tok::kw___builtin_source_location: {
27882792
// Attempt to consume the r-paren.
@@ -2799,6 +2803,8 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
27992803
return SourceLocExpr::FileName;
28002804
case tok::kw___builtin_FUNCTION:
28012805
return SourceLocExpr::Function;
2806+
case tok::kw___builtin_FUNCSIG:
2807+
return SourceLocExpr::FuncSig;
28022808
case tok::kw___builtin_LINE:
28032809
return SourceLocExpr::Line;
28042810
case tok::kw___builtin_COLUMN:

clang/lib/Sema/SemaExpr.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17181,7 +17181,8 @@ ExprResult Sema::ActOnSourceLocExpr(SourceLocExpr::IdentKind Kind,
1718117181
switch (Kind) {
1718217182
case SourceLocExpr::File:
1718317183
case SourceLocExpr::FileName:
17184-
case SourceLocExpr::Function: {
17184+
case SourceLocExpr::Function:
17185+
case SourceLocExpr::FuncSig: {
1718517186
QualType ArrTy = Context.getStringLiteralArrayType(Context.CharTy, 0);
1718617187
ResultTy =
1718717188
Context.getPointerType(ArrTy->getAsArrayTypeUnsafe()->getElementType());

clang/test/Preprocessor/feature_tests.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// RUN: %clang_cc1 %s -triple=i686-apple-darwin9 -target-cpu pentium4 -verify -DVERIFY
22
// RUN: %clang_cc1 %s -E -triple=i686-apple-darwin9 -target-cpu pentium4
3+
// RUN: %clang_cc1 %s -triple=i686-apple-darwin9 -target-cpu pentium4 -fms-extensions -DMS -verify -DVERIFY
4+
// RUN: %clang_cc1 %s -E -triple=i686-apple-darwin9 -target-cpu pentium4 -fms-extensions -DMS
35
#ifndef __has_feature
46
#error Should have __has_feature
57
#endif
@@ -31,6 +33,14 @@
3133
#error Clang should have these
3234
#endif
3335

36+
#ifdef MS
37+
#if !__has_builtin(__builtin_FUNCSIG)
38+
#error Clang should have this
39+
#endif
40+
#elif __has_builtin(__builtin_FUNCSIG)
41+
#error Clang should not have this without '-fms-extensions'
42+
#endif
43+
3444
// These are C++-only builtins.
3545
#if __has_builtin(__array_rank) || \
3646
__has_builtin(__underlying_type) || \

clang/test/Preprocessor/feature_tests.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %clang_cc1 %s -triple=i686-apple-darwin9 -verify -DVERIFY
2+
// RUN: %clang_cc1 %s -triple=i686-apple-darwin9 -fms-extensions -DMS -verify -DVERIFY
23

34
#ifndef __has_feature
45
#error Should have __has_feature
@@ -34,6 +35,14 @@
3435
#error Clang should have these
3536
#endif
3637

38+
#ifdef MS
39+
#if !__has_builtin(__builtin_FUNCSIG)
40+
#error Clang should have this
41+
#endif
42+
#elif __has_builtin(__builtin_FUNCSIG)
43+
#error Clang should not have this without '-fms-extensions'
44+
#endif
45+
3746
// This is a C-only builtin.
3847
#if __has_builtin(__builtin_types_compatible_p)
3948
#error Clang should not have this in C++ mode

clang/test/Sema/source_location.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// RUN: %clang_cc1 -std=c90 -fconst-strings -DCONST_STRINGS -verify %s
22
// RUN: %clang_cc1 -std=c90 -verify %s
3+
// RUN: %clang_cc1 -std=c90 -fms-extensions -DMS -fconst-strings -DCONST_STRINGS -verify %s
4+
// RUN: %clang_cc1 -std=c90 -fms-extensions -DMS -verify %s
35

46
// expected-no-diagnostics
57

@@ -13,13 +15,19 @@ const unsigned COL = __builtin_COLUMN();
1315
#ifndef CONST_STRINGS
1416
char *const NCFILE = __builtin_FILE();
1517
char *const NCFUNC = __builtin_FUNCTION();
18+
#ifdef MS
19+
char *const NCFNSG = __builtin_FUNCSIG();
20+
#endif
1621
#endif
1722

1823
#ifdef CONST_STRINGS
1924
_Static_assert(IsEqual(__builtin_FILE(), __FILE__), "");
2025
_Static_assert(IsEqual(__builtin_FILE_NAME(), __FILE_NAME__), "");
2126
_Static_assert(__builtin_LINE() == __LINE__, "");
2227
_Static_assert(IsEqual("", __builtin_FUNCTION()), "");
28+
#ifdef MS
29+
_Static_assert(IsEqual("", __builtin_FUNCSIG()), "");
30+
#endif
2331

2432
#line 42 "my_file.c"
2533
_Static_assert(__builtin_LINE() == 42, "");
@@ -30,5 +38,8 @@ _Static_assert(__builtin_COLUMN() == __builtin_strlen("_Static_assert(_"), "");
3038

3139
void foo(void) {
3240
_Static_assert(IsEqual(__builtin_FUNCTION(), "foo"), "");
41+
#ifdef MS
42+
_Static_assert(IsEqual(__builtin_FUNCSIG(), "void __cdecl foo(void)"), "");
43+
#endif
3344
}
3445
#endif // CONST_STRINGS

clang/test/SemaCXX/source_location.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fexceptions -verify %s
22
// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -DUSE_CONSTEVAL -fexceptions -verify %s
3+
// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fms-extensions -DMS -fexceptions -verify %s
4+
// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -fms-extensions -DMS -DUSE_CONSTEVAL -fexceptions -verify %s
35
// expected-no-diagnostics
46

57
#define assert(...) ((__VA_ARGS__) ? ((void)0) : throw 42)
@@ -86,6 +88,9 @@ static_assert(is_same<decltype(__builtin_COLUMN()), unsigned>);
8688
static_assert(is_same<decltype(__builtin_FILE()), const char *>);
8789
static_assert(is_same<decltype(__builtin_FILE_NAME()), const char *>);
8890
static_assert(is_same<decltype(__builtin_FUNCTION()), const char *>);
91+
#ifdef MS
92+
static_assert(is_same<decltype(__builtin_FUNCSIG()), const char *>);
93+
#endif
8994
static_assert(is_same<decltype(__builtin_source_location()), const std::source_location::public_impl_alias *>);
9095

9196
// test noexcept
@@ -94,6 +99,9 @@ static_assert(noexcept(__builtin_COLUMN()));
9499
static_assert(noexcept(__builtin_FILE()));
95100
static_assert(noexcept(__builtin_FILE_NAME()));
96101
static_assert(noexcept(__builtin_FUNCTION()));
102+
#ifdef MS
103+
static_assert(noexcept(__builtin_FUNCSIG()));
104+
#endif
97105
static_assert(noexcept(__builtin_source_location()));
98106

99107
//===----------------------------------------------------------------------===//
@@ -450,6 +458,57 @@ static_assert(is_equal(global_sl.function(), ""));
450458

451459
} // namespace test_func
452460

461+
//===----------------------------------------------------------------------===//
462+
// __builtin_FUNCSIG()
463+
//===----------------------------------------------------------------------===//
464+
465+
#ifdef MS
466+
namespace test_funcsig {
467+
468+
constexpr const char *test_funcsig_simple(const char *f = __builtin_FUNCSIG()) {
469+
return f;
470+
}
471+
constexpr const char *get_funcsig() {
472+
return __FUNCSIG__;
473+
}
474+
constexpr bool test_funcsig() {
475+
return is_equal(__FUNCSIG__, test_funcsig_simple()) &&
476+
!is_equal(get_funcsig(), test_funcsig_simple());
477+
}
478+
static_assert(test_funcsig());
479+
480+
template <class T>
481+
constexpr Pair<const char*, const char*> test_funcsig_template(T, const char* f = __builtin_FUNCSIG()) {
482+
return {f, __builtin_FUNCSIG()};
483+
}
484+
template <class T>
485+
void func_template_tests() {
486+
constexpr auto P = test_funcsig_template(42);
487+
static_assert(is_equal(P.first, __FUNCSIG__), "");
488+
static_assert(!is_equal(P.second, __FUNCSIG__), "");
489+
}
490+
template void func_template_tests<int>();
491+
492+
template <class = int, class T = const char*>
493+
struct TestCtor {
494+
T funcsig = __builtin_FUNCSIG();
495+
T ctor_funcsig;
496+
TestCtor() = default;
497+
template <class F = const char*>
498+
constexpr TestCtor(int, F f = __builtin_FUNCSIG()) : ctor_funcsig(f) {}
499+
};
500+
void ctor_tests() {
501+
constexpr TestCtor<> Template{42};
502+
static_assert(is_equal(Template.funcsig, "__cdecl test_funcsig::TestCtor<>::TestCtor(int, F) [T = const char *, F = const char *]"));
503+
static_assert(is_equal(Template.ctor_funcsig, __FUNCSIG__));
504+
}
505+
506+
constexpr const char* global_funcsig = __builtin_FUNCSIG();
507+
static_assert(is_equal(global_funcsig, ""));
508+
509+
} // namespace test_funcsig
510+
#endif
511+
453512
//===----------------------------------------------------------------------===//
454513
// __builtin_COLUMN()
455514
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)