diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp index 5976d4c3e7131..8f76b51ac0334 100644 --- a/clang/lib/AST/Interp/InterpBuiltin.cpp +++ b/clang/lib/AST/Interp/InterpBuiltin.cpp @@ -645,6 +645,19 @@ static bool interp__builtin_move(InterpState &S, CodePtr OpPC, return Func->getDecl()->isConstexpr(); } +static bool interp__builtin_eh_return_data_regno(InterpState &S, CodePtr OpPC, + const InterpFrame *Frame, + const Function *Func, + const CallExpr *Call) { + PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); + APSInt Arg = peekToAPSInt(S.Stk, ArgT); + + int Result = + S.getCtx().getTargetInfo().getEHDataRegisterNumber(Arg.getZExtValue()); + pushInt(S, Result); + return true; +} + bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *Call) { InterpFrame *Frame = S.Current; @@ -869,6 +882,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, return false; break; + case Builtin::BI__builtin_eh_return_data_regno: + if (!interp__builtin_eh_return_data_regno(S, OpPC, Frame, F, Call)) + return false; + break; + default: return false; } diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp index ce7c8bd357908..d6ed2d862b094 100644 --- a/clang/test/AST/Interp/builtin-functions.cpp +++ b/clang/test/AST/Interp/builtin-functions.cpp @@ -363,3 +363,16 @@ namespace ffs { char ffs6[__builtin_ffsl(0x10L) == 5 ? 1 : -1]; char ffs7[__builtin_ffsll(0x100LL) == 9 ? 1 : -1]; } + +namespace EhReturnDataRegno { + void test11(int X) { + switch (X) { + case __builtin_eh_return_data_regno(0): // constant foldable. + break; + } + + __builtin_eh_return_data_regno(X); // expected-error {{argument to '__builtin_eh_return_data_regno' must be a constant integer}} \ + // ref-error {{argument to '__builtin_eh_return_data_regno' must be a constant integer}} + + } +}