diff options
-rw-r--r-- | clang/include/clang/Basic/Builtins.td | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 22 | ||||
-rw-r--r-- | clang/test/SemaCXX/alloc-token.cpp | 23 |
3 files changed, 52 insertions, 0 deletions
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index a350acd..a2c2021 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4727,6 +4727,13 @@ def PtrauthStringDiscriminator : Builtin { let Prototype = "size_t(char const*)"; } +// AllocToken builtins. +def InferAllocToken : Builtin { + let Spellings = ["__builtin_infer_alloc_token"]; + let Attributes = [NoThrow, Const, Pure, CustomTypeChecking, Constexpr, UnevaluatedArguments]; + let Prototype = "size_t(...)"; +} + // OpenCL v2.0 s6.13.16, s9.17.3.5 - Pipe functions. // We need the generic prototype, since the packet type could be anything. def ReadPipe : OCLPipeLangBuiltin { diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 2990fd6..f99c01e 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1498,6 +1498,24 @@ static void builtinAllocaAddrSpace(Sema &S, CallExpr *TheCall) { TheCall->setType(S.Context.getPointerType(RT)); } +static bool checkBuiltinInferAllocToken(Sema &S, CallExpr *TheCall) { + if (S.checkArgCountAtLeast(TheCall, 1)) + return true; + + for (Expr *Arg : TheCall->arguments()) { + // If argument is dependent on a template parameter, we can't resolve now. + if (Arg->isTypeDependent() || Arg->isValueDependent()) + continue; + // Reject void types. + QualType ArgTy = Arg->IgnoreParenImpCasts()->getType(); + if (ArgTy->isVoidType()) + return S.Diag(Arg->getBeginLoc(), diag::err_param_with_void_type); + } + + TheCall->setType(S.Context.UnsignedLongLongTy); + return false; +} + namespace { enum PointerAuthOpKind { PAO_Strip, @@ -2779,6 +2797,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, builtinAllocaAddrSpace(*this, TheCall); } break; + case Builtin::BI__builtin_infer_alloc_token: + if (checkBuiltinInferAllocToken(*this, TheCall)) + return ExprError(); + break; case Builtin::BI__arithmetic_fence: if (BuiltinArithmeticFence(TheCall)) return ExprError(); diff --git a/clang/test/SemaCXX/alloc-token.cpp b/clang/test/SemaCXX/alloc-token.cpp new file mode 100644 index 0000000..a267442 --- /dev/null +++ b/clang/test/SemaCXX/alloc-token.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -fsyntax-only -verify %s -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -fsyntax-only -verify %s -falloc-token-mode=typehash -DMODE_TYPEHASH + +#if !__has_builtin(__builtin_infer_alloc_token) +#error "missing __builtin_infer_alloc_token" +#endif + +template <typename T = void> +void template_test() { + __builtin_infer_alloc_token(T()); // no error if not instantiated +} + +template <typename T> +void negative_template_test() { + __builtin_infer_alloc_token(T()); // expected-error {{argument may not have 'void' type}} +} + +void negative_tests() { + __builtin_infer_alloc_token(); // expected-error {{too few arguments to function call}} + __builtin_infer_alloc_token((void)0); // expected-error {{argument may not have 'void' type}} + negative_template_test<void>(); // expected-note {{in instantiation of function template specialization 'negative_template_test<void>' requested here}} +} |