diff options
Diffstat (limited to 'clang/lib/Sema/SemaType.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaType.cpp | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 33b1d8ca4dfa..eba7267904fb 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2552,6 +2552,12 @@ bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) { return true; } + // __ptrauth is illegal on a function return type. + if (T.getPointerAuth()) { + Diag(Loc, diag::err_ptrauth_qualifier_invalid) << T << 0; + return true; + } + if (T.hasNonTrivialToPrimitiveDestructCUnion() || T.hasNonTrivialToPrimitiveCopyCUnion()) checkNonTrivialCUnion(T, Loc, NTCUC_FunctionReturn, @@ -2657,6 +2663,10 @@ QualType Sema::BuildFunctionType(QualType T, } else if (ParamType->isWebAssemblyTableType()) { Diag(Loc, diag::err_wasm_table_as_function_parameter); Invalid = true; + } else if (ParamType.getPointerAuth()) { + // __ptrauth is illegal on a function return type. + Diag(Loc, diag::err_ptrauth_qualifier_invalid) << T << 1; + Invalid = true; } // C++2a [dcl.fct]p4: @@ -4974,6 +4984,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } } + // __ptrauth is illegal on a function return type. + if (T.getPointerAuth()) { + S.Diag(DeclType.Loc, diag::err_ptrauth_qualifier_invalid) << T << 0; + } + if (LangOpts.OpenCL) { // OpenCL v2.0 s6.12.5 - A block cannot be the return value of a // function. @@ -8333,6 +8348,65 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr, CurType = S.Context.getVectorType(CurType, numElts, VecKind); } +/// Handle the __ptrauth qualifier. +static void HandlePtrAuthQualifier(ASTContext &Ctx, QualType &T, + const ParsedAttr &Attr, Sema &S) { + + assert((Attr.getNumArgs() > 0 && Attr.getNumArgs() <= 3) && + "__ptrauth qualifier takes between 1 and 3 arguments"); + Expr *KeyArg = Attr.getArgAsExpr(0); + Expr *IsAddressDiscriminatedArg = + Attr.getNumArgs() >= 2 ? Attr.getArgAsExpr(1) : nullptr; + Expr *ExtraDiscriminatorArg = + Attr.getNumArgs() >= 3 ? Attr.getArgAsExpr(2) : nullptr; + + unsigned Key; + if (S.checkConstantPointerAuthKey(KeyArg, Key)) { + Attr.setInvalid(); + return; + } + assert(Key <= PointerAuthQualifier::MaxKey && "ptrauth key is out of range"); + + bool IsInvalid = false; + unsigned IsAddressDiscriminated, ExtraDiscriminator; + IsInvalid |= !S.checkPointerAuthDiscriminatorArg(IsAddressDiscriminatedArg, + Sema::PADAK_AddrDiscPtrAuth, + IsAddressDiscriminated); + IsInvalid |= !S.checkPointerAuthDiscriminatorArg( + ExtraDiscriminatorArg, Sema::PADAK_ExtraDiscPtrAuth, ExtraDiscriminator); + + if (IsInvalid) { + Attr.setInvalid(); + return; + } + + if (!T->isSignableType() && !T->isDependentType()) { + S.Diag(Attr.getLoc(), diag::err_ptrauth_qualifier_nonpointer) << T; + Attr.setInvalid(); + return; + } + + if (T.getPointerAuth()) { + S.Diag(Attr.getLoc(), diag::err_ptrauth_qualifier_redundant) + << T << Attr.getAttrName()->getName(); + Attr.setInvalid(); + return; + } + + if (!S.getLangOpts().PointerAuthIntrinsics) { + S.Diag(Attr.getLoc(), diag::err_ptrauth_disabled) << Attr.getRange(); + Attr.setInvalid(); + return; + } + + assert((!IsAddressDiscriminatedArg || IsAddressDiscriminated <= 1) && + "address discriminator arg should be either 0 or 1"); + PointerAuthQualifier Qual = PointerAuthQualifier::Create( + Key, IsAddressDiscriminated, ExtraDiscriminator, + PointerAuthenticationMode::SignAndAuth, false, false); + T = S.Context.getPointerAuthType(T, Qual); +} + /// HandleArmSveVectorBitsTypeAttr - The "arm_sve_vector_bits" attribute is /// used to create fixed-length versions of sizeless SVE types defined by /// the ACLE, such as svint32_t and svbool_t. @@ -8788,6 +8862,11 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, HandleOpenCLAccessAttr(type, attr, state.getSema()); attr.setUsedAsTypeAttr(); break; + case ParsedAttr::AT_PointerAuth: + HandlePtrAuthQualifier(state.getSema().Context, type, attr, + state.getSema()); + attr.setUsedAsTypeAttr(); + break; case ParsedAttr::AT_LifetimeBound: if (TAL == TAL_DeclChunk) HandleLifetimeBoundAttr(state, type, attr); |
