[clang] 78d8312 - [Clang][clang-cl] Implement `__builtin_FUNCSIG`
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Fri May 19 09:02:54 PDT 2023
Author: Jakub Mazurkiewicz
Date: 2023-05-19T12:02:44-04:00
New Revision: 78d8312acea96f58f13a876f98d241590c16d530
URL: https://github.com/llvm/llvm-project/commit/78d8312acea96f58f13a876f98d241590c16d530
DIFF: https://github.com/llvm/llvm-project/commit/78d8312acea96f58f13a876f98d241590c16d530.diff
LOG: [Clang][clang-cl] Implement `__builtin_FUNCSIG`
This patch implements __builtin_FUNCSIG intrinsic which returns the same string as __FUNCSIG__.
Fixes https://github.com/llvm/llvm-project/issues/58951
Differential Revision: https://reviews.llvm.org/D150183
Added:
Modified:
clang/docs/LanguageExtensions.rst
clang/docs/ReleaseNotes.rst
clang/include/clang/AST/Expr.h
clang/include/clang/Basic/TokenKinds.def
clang/include/clang/Sema/Sema.h
clang/lib/AST/Expr.cpp
clang/lib/Parse/ParseExpr.cpp
clang/lib/Sema/SemaExpr.cpp
clang/test/Preprocessor/feature_tests.c
clang/test/Preprocessor/feature_tests.cpp
clang/test/Sema/source_location.c
clang/test/SemaCXX/source_location.cpp
Removed:
################################################################################
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 632a5cf1a7d02..5b186c4f81774 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -3711,7 +3711,7 @@ Source location builtins
Clang provides builtins to support C++ standard library implementation
of ``std::source_location`` as specified in C++20. With the exception
-of ``__builtin_COLUMN`` and ``__builtin_FILE_NAME``,
+of ``__builtin_COLUMN``, ``__builtin_FILE_NAME`` and ``__builtin_FUNCSIG``,
these builtins are also implemented by GCC.
**Syntax**:
@@ -3721,6 +3721,7 @@ these builtins are also implemented by GCC.
const char *__builtin_FILE();
const char *__builtin_FILE_NAME(); // Clang only
const char *__builtin_FUNCTION();
+ const char *__builtin_FUNCSIG(); // Microsoft
unsigned __builtin_LINE();
unsigned __builtin_COLUMN(); // Clang only
const std::source_location::__impl *__builtin_source_location();
@@ -3750,11 +3751,12 @@ these builtins are also implemented by GCC.
**Description**:
-The builtins ``__builtin_LINE``, ``__builtin_FUNCTION``, ``__builtin_FILE`` and
-``__builtin_FILE_NAME`` return the values, at the "invocation point", for
-``__LINE__``, ``__FUNCTION__``, ``__FILE__`` and ``__FILE_NAME__`` respectively.
-``__builtin_COLUMN`` similarly returns the column,
-though there is no corresponding macro. These builtins are constant expressions.
+The builtins ``__builtin_LINE``, ``__builtin_FUNCTION``, ``__builtin_FUNCSIG``,
+``__builtin_FILE`` and ``__builtin_FILE_NAME`` return the values, at the
+"invocation point", for ``__LINE__``, ``__FUNCTION__``, ``__FUNCSIG__``,
+``__FILE__`` and ``__FILE_NAME__`` respectively. ``__builtin_COLUMN`` similarly
+returns the column, though there is no corresponding macro. These builtins are
+constant expressions.
When the builtins appear as part of a default function argument the invocation
point is the location of the caller. When the builtins appear as part of a
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 1dd3d8a0ed80c..9bcc17b0c5ff8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -198,6 +198,9 @@ Non-comprehensive list of changes in this release
``memcmp(&lhs, &rhs, sizeof(T)) == 0``.
- Clang now ignores null directives outside of the include guard when deciding
whether a file can be enabled for the multiple-include optimization.
+- Clang now support ``__builtin_FUNCSIG()`` which retruns the same information
+ as the ``__FUNCSIG__`` macro (available only with ``-fms-extensions`` flag).
+ This fixes (`#58951 <https://github.com/llvm/llvm-project/issues/58951>`_).
New Compiler Flags
------------------
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index db4316d8faf1f..22cbf23ac2a4c 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4691,14 +4691,22 @@ class VAArgExpr : public Expr {
};
/// Represents a function call to one of __builtin_LINE(), __builtin_COLUMN(),
-/// __builtin_FUNCTION(), __builtin_FILE(), __builtin_FILE_NAME(),
-/// or __builtin_source_location().
+/// __builtin_FUNCTION(), __builtin_FUNCSIG(), __builtin_FILE(),
+/// __builtin_FILE_NAME() or __builtin_source_location().
class SourceLocExpr final : public Expr {
SourceLocation BuiltinLoc, RParenLoc;
DeclContext *ParentContext;
public:
- enum IdentKind { Function, File, FileName, Line, Column, SourceLocStruct };
+ enum IdentKind {
+ Function,
+ FuncSig,
+ File,
+ FileName,
+ Line,
+ Column,
+ SourceLocStruct
+ };
SourceLocExpr(const ASTContext &Ctx, IdentKind Type, QualType ResultTy,
SourceLocation BLoc, SourceLocation RParenLoc,
@@ -4724,6 +4732,7 @@ class SourceLocExpr final : public Expr {
case File:
case FileName:
case Function:
+ case FuncSig:
case SourceLocStruct:
return false;
case Line:
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index ae67209d9b9e2..7c3a55cb76348 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -438,6 +438,7 @@ KEYWORD(__builtin_offsetof , KEYALL)
KEYWORD(__builtin_FILE , KEYALL)
KEYWORD(__builtin_FILE_NAME , KEYALL)
KEYWORD(__builtin_FUNCTION , KEYALL)
+KEYWORD(__builtin_FUNCSIG , KEYMS)
KEYWORD(__builtin_LINE , KEYALL)
KEYWORD(__builtin_COLUMN , KEYALL)
KEYWORD(__builtin_source_location , KEYCXX)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index aae1d9ce3208e..6e2734da2bea6 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -6006,8 +6006,8 @@ class Sema final {
ExprResult BuildVAArgExpr(SourceLocation BuiltinLoc, Expr *E,
TypeSourceInfo *TInfo, SourceLocation RPLoc);
- // __builtin_LINE(), __builtin_FUNCTION(), __builtin_FILE(),
- // __builtin_COLUMN(), __builtin_source_location()
+ // __builtin_LINE(), __builtin_FUNCTION(), __builtin_FUNCSIG(),
+ // __builtin_FILE(), __builtin_COLUMN(), __builtin_source_location()
ExprResult ActOnSourceLocExpr(SourceLocExpr::IdentKind Kind,
SourceLocation BuiltinLoc,
SourceLocation RPLoc);
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 588a7ad322b9a..958f4e9042319 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -2247,6 +2247,8 @@ StringRef SourceLocExpr::getBuiltinStr() const {
return "__builtin_FILE_NAME";
case Function:
return "__builtin_FUNCTION";
+ case FuncSig:
+ return "__builtin_FUNCSIG";
case Line:
return "__builtin_LINE";
case Column:
@@ -2297,11 +2299,14 @@ APValue SourceLocExpr::EvaluateInContext(const ASTContext &Ctx,
Ctx.getTargetInfo());
return MakeStringLiteral(Path);
}
- case SourceLocExpr::Function: {
+ case SourceLocExpr::Function:
+ case SourceLocExpr::FuncSig: {
const auto *CurDecl = dyn_cast<Decl>(Context);
+ const auto Kind = getIdentKind() == SourceLocExpr::Function
+ ? PredefinedExpr::Function
+ : PredefinedExpr::FuncSig;
return MakeStringLiteral(
- CurDecl ? PredefinedExpr::ComputeName(PredefinedExpr::Function, CurDecl)
- : std::string(""));
+ CurDecl ? PredefinedExpr::ComputeName(Kind, CurDecl) : std::string(""));
}
case SourceLocExpr::Line:
case SourceLocExpr::Column: {
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index b99baf476592f..57bb8f609592f 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -792,6 +792,7 @@ class CastExpressionIdValidator final : public CorrectionCandidateCallback {
/// [GNU] '__builtin_FILE' '(' ')'
/// [CLANG] '__builtin_FILE_NAME' '(' ')'
/// [GNU] '__builtin_FUNCTION' '(' ')'
+/// [MS] '__builtin_FUNCSIG' '(' ')'
/// [GNU] '__builtin_LINE' '(' ')'
/// [CLANG] '__builtin_COLUMN' '(' ')'
/// [GNU] '__builtin_source_location' '(' ')'
@@ -1321,6 +1322,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
case tok::kw___builtin_FILE:
case tok::kw___builtin_FILE_NAME:
case tok::kw___builtin_FUNCTION:
+ case tok::kw___builtin_FUNCSIG:
case tok::kw___builtin_LINE:
case tok::kw___builtin_source_location:
if (NotPrimaryExpression)
@@ -2547,6 +2549,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
/// [GNU] '__builtin_FILE' '(' ')'
/// [CLANG] '__builtin_FILE_NAME' '(' ')'
/// [GNU] '__builtin_FUNCTION' '(' ')'
+/// [MS] '__builtin_FUNCSIG' '(' ')'
/// [GNU] '__builtin_LINE' '(' ')'
/// [CLANG] '__builtin_COLUMN' '(' ')'
/// [GNU] '__builtin_source_location' '(' ')'
@@ -2783,6 +2786,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
case tok::kw___builtin_FILE:
case tok::kw___builtin_FILE_NAME:
case tok::kw___builtin_FUNCTION:
+ case tok::kw___builtin_FUNCSIG:
case tok::kw___builtin_LINE:
case tok::kw___builtin_source_location: {
// Attempt to consume the r-paren.
@@ -2799,6 +2803,8 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
return SourceLocExpr::FileName;
case tok::kw___builtin_FUNCTION:
return SourceLocExpr::Function;
+ case tok::kw___builtin_FUNCSIG:
+ return SourceLocExpr::FuncSig;
case tok::kw___builtin_LINE:
return SourceLocExpr::Line;
case tok::kw___builtin_COLUMN:
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index e7a555b991bf0..ac0b2ad6eb7ee 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -17181,7 +17181,8 @@ ExprResult Sema::ActOnSourceLocExpr(SourceLocExpr::IdentKind Kind,
switch (Kind) {
case SourceLocExpr::File:
case SourceLocExpr::FileName:
- case SourceLocExpr::Function: {
+ case SourceLocExpr::Function:
+ case SourceLocExpr::FuncSig: {
QualType ArrTy = Context.getStringLiteralArrayType(Context.CharTy, 0);
ResultTy =
Context.getPointerType(ArrTy->getAsArrayTypeUnsafe()->getElementType());
diff --git a/clang/test/Preprocessor/feature_tests.c b/clang/test/Preprocessor/feature_tests.c
index 07ca02279b911..e8aecfb82cb3b 100644
--- a/clang/test/Preprocessor/feature_tests.c
+++ b/clang/test/Preprocessor/feature_tests.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 %s -triple=i686-apple-darwin9 -target-cpu pentium4 -verify -DVERIFY
// RUN: %clang_cc1 %s -E -triple=i686-apple-darwin9 -target-cpu pentium4
+// RUN: %clang_cc1 %s -triple=i686-apple-darwin9 -target-cpu pentium4 -fms-extensions -DMS -verify -DVERIFY
+// RUN: %clang_cc1 %s -E -triple=i686-apple-darwin9 -target-cpu pentium4 -fms-extensions -DMS
#ifndef __has_feature
#error Should have __has_feature
#endif
@@ -31,6 +33,14 @@
#error Clang should have these
#endif
+#ifdef MS
+#if !__has_builtin(__builtin_FUNCSIG)
+#error Clang should have this
+#endif
+#elif __has_builtin(__builtin_FUNCSIG)
+#error Clang should not have this without '-fms-extensions'
+#endif
+
// These are C++-only builtins.
#if __has_builtin(__array_rank) || \
__has_builtin(__underlying_type) || \
diff --git a/clang/test/Preprocessor/feature_tests.cpp b/clang/test/Preprocessor/feature_tests.cpp
index 810cfe88cae5f..00421d74e6282 100644
--- a/clang/test/Preprocessor/feature_tests.cpp
+++ b/clang/test/Preprocessor/feature_tests.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 %s -triple=i686-apple-darwin9 -verify -DVERIFY
+// RUN: %clang_cc1 %s -triple=i686-apple-darwin9 -fms-extensions -DMS -verify -DVERIFY
#ifndef __has_feature
#error Should have __has_feature
@@ -34,6 +35,14 @@
#error Clang should have these
#endif
+#ifdef MS
+#if !__has_builtin(__builtin_FUNCSIG)
+#error Clang should have this
+#endif
+#elif __has_builtin(__builtin_FUNCSIG)
+#error Clang should not have this without '-fms-extensions'
+#endif
+
// This is a C-only builtin.
#if __has_builtin(__builtin_types_compatible_p)
#error Clang should not have this in C++ mode
diff --git a/clang/test/Sema/source_location.c b/clang/test/Sema/source_location.c
index e4faf042d4876..e0030c634dd88 100644
--- a/clang/test/Sema/source_location.c
+++ b/clang/test/Sema/source_location.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -std=c90 -fconst-strings -DCONST_STRINGS -verify %s
// RUN: %clang_cc1 -std=c90 -verify %s
+// RUN: %clang_cc1 -std=c90 -fms-extensions -DMS -fconst-strings -DCONST_STRINGS -verify %s
+// RUN: %clang_cc1 -std=c90 -fms-extensions -DMS -verify %s
// expected-no-diagnostics
@@ -13,6 +15,9 @@ const unsigned COL = __builtin_COLUMN();
#ifndef CONST_STRINGS
char *const NCFILE = __builtin_FILE();
char *const NCFUNC = __builtin_FUNCTION();
+#ifdef MS
+char *const NCFNSG = __builtin_FUNCSIG();
+#endif
#endif
#ifdef CONST_STRINGS
@@ -20,6 +25,9 @@ _Static_assert(IsEqual(__builtin_FILE(), __FILE__), "");
_Static_assert(IsEqual(__builtin_FILE_NAME(), __FILE_NAME__), "");
_Static_assert(__builtin_LINE() == __LINE__, "");
_Static_assert(IsEqual("", __builtin_FUNCTION()), "");
+#ifdef MS
+_Static_assert(IsEqual("", __builtin_FUNCSIG()), "");
+#endif
#line 42 "my_file.c"
_Static_assert(__builtin_LINE() == 42, "");
@@ -30,5 +38,8 @@ _Static_assert(__builtin_COLUMN() == __builtin_strlen("_Static_assert(_"), "");
void foo(void) {
_Static_assert(IsEqual(__builtin_FUNCTION(), "foo"), "");
+#ifdef MS
+ _Static_assert(IsEqual(__builtin_FUNCSIG(), "void __cdecl foo(void)"), "");
+#endif
}
#endif // CONST_STRINGS
diff --git a/clang/test/SemaCXX/source_location.cpp b/clang/test/SemaCXX/source_location.cpp
index 06f90f9251643..6ff58d4ee8ca1 100644
--- a/clang/test/SemaCXX/source_location.cpp
+++ b/clang/test/SemaCXX/source_location.cpp
@@ -1,5 +1,7 @@
// 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++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
// expected-no-diagnostics
#define assert(...) ((__VA_ARGS__) ? ((void)0) : throw 42)
@@ -86,6 +88,9 @@ static_assert(is_same<decltype(__builtin_COLUMN()), unsigned>);
static_assert(is_same<decltype(__builtin_FILE()), const char *>);
static_assert(is_same<decltype(__builtin_FILE_NAME()), const char *>);
static_assert(is_same<decltype(__builtin_FUNCTION()), const char *>);
+#ifdef MS
+static_assert(is_same<decltype(__builtin_FUNCSIG()), const char *>);
+#endif
static_assert(is_same<decltype(__builtin_source_location()), const std::source_location::public_impl_alias *>);
// test noexcept
@@ -94,6 +99,9 @@ static_assert(noexcept(__builtin_COLUMN()));
static_assert(noexcept(__builtin_FILE()));
static_assert(noexcept(__builtin_FILE_NAME()));
static_assert(noexcept(__builtin_FUNCTION()));
+#ifdef MS
+static_assert(noexcept(__builtin_FUNCSIG()));
+#endif
static_assert(noexcept(__builtin_source_location()));
//===----------------------------------------------------------------------===//
@@ -450,6 +458,57 @@ static_assert(is_equal(global_sl.function(), ""));
} // namespace test_func
+//===----------------------------------------------------------------------===//
+// __builtin_FUNCSIG()
+//===----------------------------------------------------------------------===//
+
+#ifdef MS
+namespace test_funcsig {
+
+constexpr const char *test_funcsig_simple(const char *f = __builtin_FUNCSIG()) {
+ return f;
+}
+constexpr const char *get_funcsig() {
+ return __FUNCSIG__;
+}
+constexpr bool test_funcsig() {
+ return is_equal(__FUNCSIG__, test_funcsig_simple()) &&
+ !is_equal(get_funcsig(), test_funcsig_simple());
+}
+static_assert(test_funcsig());
+
+template <class T>
+constexpr Pair<const char*, const char*> test_funcsig_template(T, const char* f = __builtin_FUNCSIG()) {
+ return {f, __builtin_FUNCSIG()};
+}
+template <class T>
+void func_template_tests() {
+ constexpr auto P = test_funcsig_template(42);
+ static_assert(is_equal(P.first, __FUNCSIG__), "");
+ static_assert(!is_equal(P.second, __FUNCSIG__), "");
+}
+template void func_template_tests<int>();
+
+template <class = int, class T = const char*>
+struct TestCtor {
+ T funcsig = __builtin_FUNCSIG();
+ T ctor_funcsig;
+ TestCtor() = default;
+ template <class F = const char*>
+ constexpr TestCtor(int, F f = __builtin_FUNCSIG()) : ctor_funcsig(f) {}
+};
+void ctor_tests() {
+ constexpr TestCtor<> Template{42};
+ static_assert(is_equal(Template.funcsig, "__cdecl test_funcsig::TestCtor<>::TestCtor(int, F) [T = const char *, F = const char *]"));
+ static_assert(is_equal(Template.ctor_funcsig, __FUNCSIG__));
+}
+
+constexpr const char* global_funcsig = __builtin_FUNCSIG();
+static_assert(is_equal(global_funcsig, ""));
+
+} // namespace test_funcsig
+#endif
+
//===----------------------------------------------------------------------===//
// __builtin_COLUMN()
//===----------------------------------------------------------------------===//
More information about the cfe-commits
mailing list