diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-01-17 20:45:01 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-01-17 20:45:01 +0000 |
commit | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (patch) | |
tree | 4adf86a776049cbf7f69a1929c4babcbbef925eb /clang/lib/Sema/SemaDeclAttr.cpp | |
parent | 7cc9cf2bf09f069cb2dd947ead05d0b54301fb71 (diff) |
Notes
Diffstat (limited to 'clang/lib/Sema/SemaDeclAttr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 347 |
1 files changed, 327 insertions, 20 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index b2be6245a814..5c51b0f9b8cb 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -23,6 +23,7 @@ #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/DeclSpec.h" @@ -1068,6 +1069,56 @@ static void handleDiagnoseIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) { S.Context, AL, Cond, Msg, DiagType, ArgDependent, cast<NamedDecl>(D))); } +static void handleNoBuiltinAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + static constexpr const StringRef kWildcard = "*"; + + llvm::SmallVector<StringRef, 16> Names; + bool HasWildcard = false; + + const auto AddBuiltinName = [&Names, &HasWildcard](StringRef Name) { + if (Name == kWildcard) + HasWildcard = true; + Names.push_back(Name); + }; + + // Add previously defined attributes. + if (const auto *NBA = D->getAttr<NoBuiltinAttr>()) + for (StringRef BuiltinName : NBA->builtinNames()) + AddBuiltinName(BuiltinName); + + // Add current attributes. + if (AL.getNumArgs() == 0) + AddBuiltinName(kWildcard); + else + for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { + StringRef BuiltinName; + SourceLocation LiteralLoc; + if (!S.checkStringLiteralArgumentAttr(AL, I, BuiltinName, &LiteralLoc)) + return; + + if (Builtin::Context::isBuiltinFunc(BuiltinName)) + AddBuiltinName(BuiltinName); + else + S.Diag(LiteralLoc, diag::warn_attribute_no_builtin_invalid_builtin_name) + << BuiltinName << AL.getAttrName()->getName(); + } + + // Repeating the same attribute is fine. + llvm::sort(Names); + Names.erase(std::unique(Names.begin(), Names.end()), Names.end()); + + // Empty no_builtin must be on its own. + if (HasWildcard && Names.size() > 1) + S.Diag(D->getLocation(), + diag::err_attribute_no_builtin_wildcard_or_builtin_name) + << AL.getAttrName()->getName(); + + if (D->hasAttr<NoBuiltinAttr>()) + D->dropAttr<NoBuiltinAttr>(); + D->addAttr(::new (S.Context) + NoBuiltinAttr(S.Context, AL, Names.data(), Names.size())); +} + static void handlePassObjectSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (D->hasAttr<PassObjectSizeAttr>()) { S.Diag(D->getBeginLoc(), diag::err_attribute_only_once_per_parameter) << AL; @@ -2549,6 +2600,29 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL, D->addAttr(newAttr); } +static void handleObjCDirectAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + // objc_direct cannot be set on methods declared in the context of a protocol + if (isa<ObjCProtocolDecl>(D->getDeclContext())) { + S.Diag(AL.getLoc(), diag::err_objc_direct_on_protocol) << false; + return; + } + + if (S.getLangOpts().ObjCRuntime.allowsDirectDispatch()) { + handleSimpleAttribute<ObjCDirectAttr>(S, D, AL); + } else { + S.Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL; + } +} + +static void handleObjCDirectMembersAttr(Sema &S, Decl *D, + const ParsedAttr &AL) { + if (S.getLangOpts().ObjCRuntime.allowsDirectDispatch()) { + handleSimpleAttribute<ObjCDirectMembersAttr>(S, D, AL); + } else { + S.Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL; + } +} + static void handleObjCMethodFamilyAttr(Sema &S, Decl *D, const ParsedAttr &AL) { const auto *M = cast<ObjCMethodDecl>(D); if (!AL.isArgIdent(0)) { @@ -2839,7 +2913,7 @@ static void handleVecTypeHint(Sema &S, Decl *D, const ParsedAttr &AL) { if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() && (ParmType->isBooleanType() || !ParmType->isIntegralType(S.getASTContext()))) { - S.Diag(AL.getLoc(), diag::err_attribute_invalid_argument) << 3 << AL; + S.Diag(AL.getLoc(), diag::err_attribute_invalid_argument) << 2 << AL; return; } @@ -2972,7 +3046,7 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) { return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) << Unsupported << None << Str; - TargetAttr::ParsedTargetAttr ParsedAttrs = TargetAttr::parse(AttrStr); + ParsedTargetAttr ParsedAttrs = TargetAttr::parse(AttrStr); if (!ParsedAttrs.Architecture.empty() && !Context.getTargetInfo().isValidCPUName(ParsedAttrs.Architecture)) @@ -2990,6 +3064,19 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) { << Unsupported << None << CurFeature; } + TargetInfo::BranchProtectionInfo BPI; + StringRef Error; + if (!ParsedAttrs.BranchProtection.empty() && + !Context.getTargetInfo().validateBranchProtection( + ParsedAttrs.BranchProtection, BPI, Error)) { + if (Error.empty()) + return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) + << Unsupported << None << "branch-protection"; + else + return Diag(LiteralLoc, diag::err_invalid_branch_protection_spec) + << Error; + } + return false; } @@ -3798,7 +3885,7 @@ void Sema::CheckAlignasUnderalignment(Decl *D) { bool Sema::checkMSInheritanceAttrOnDefinition( CXXRecordDecl *RD, SourceRange Range, bool BestCase, - MSInheritanceAttr::Spelling SemanticSpelling) { + MSInheritanceModel ExplicitModel) { assert(RD->hasDefinition() && "RD has no definition!"); // We may not have seen base specifiers or any virtual methods yet. We will @@ -3807,14 +3894,14 @@ bool Sema::checkMSInheritanceAttrOnDefinition( return false; // The unspecified model never matches what a definition could need. - if (SemanticSpelling == MSInheritanceAttr::Keyword_unspecified_inheritance) + if (ExplicitModel == MSInheritanceModel::Unspecified) return false; if (BestCase) { - if (RD->calculateInheritanceModel() == SemanticSpelling) + if (RD->calculateInheritanceModel() == ExplicitModel) return false; } else { - if (RD->calculateInheritanceModel() <= SemanticSpelling) + if (RD->calculateInheritanceModel() <= ExplicitModel) return false; } @@ -4367,12 +4454,10 @@ static void handleLifetimeCategoryAttr(Sema &S, Decl *D, const ParsedAttr &AL) { ParmType = S.GetTypeFromParser(AL.getTypeArg(), &DerefTypeLoc); unsigned SelectIdx = ~0U; - if (ParmType->isVoidType()) + if (ParmType->isReferenceType()) SelectIdx = 0; - else if (ParmType->isReferenceType()) - SelectIdx = 1; else if (ParmType->isArrayType()) - SelectIdx = 2; + SelectIdx = 1; if (SelectIdx != ~0U) { S.Diag(AL.getLoc(), diag::err_attribute_invalid_argument) @@ -4830,6 +4915,54 @@ static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { XRayLogArgsAttr(S.Context, AL, ArgCount.getSourceIndex())); } +static void handlePatchableFunctionEntryAttr(Sema &S, Decl *D, + const ParsedAttr &AL) { + uint32_t Count = 0, Offset = 0; + if (!checkUInt32Argument(S, AL, AL.getArgAsExpr(0), Count, 0, true)) + return; + if (AL.getNumArgs() == 2) { + Expr *Arg = AL.getArgAsExpr(1); + if (!checkUInt32Argument(S, AL, Arg, Offset, 1, true)) + return; + if (Offset) { + S.Diag(getAttrLoc(AL), diag::err_attribute_argument_out_of_range) + << &AL << 0 << 0 << Arg->getBeginLoc(); + return; + } + } + D->addAttr(::new (S.Context) + PatchableFunctionEntryAttr(S.Context, AL, Count, Offset)); +} + +static bool ArmMveAliasValid(unsigned BuiltinID, StringRef AliasName) { + if (AliasName.startswith("__arm_")) + AliasName = AliasName.substr(6); + switch (BuiltinID) { +#include "clang/Basic/arm_mve_builtin_aliases.inc" + default: + return false; + } +} + +static void handleArmMveAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + if (!AL.isArgIdent(0)) { + S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) + << AL << 1 << AANT_ArgumentIdentifier; + return; + } + + IdentifierInfo *Ident = AL.getArgAsIdent(0)->Ident; + unsigned BuiltinID = Ident->getBuiltinID(); + + if (!ArmMveAliasValid(BuiltinID, + cast<FunctionDecl>(D)->getIdentifier()->getName())) { + S.Diag(AL.getLoc(), diag::err_attribute_arm_mve_alias); + return; + } + + D->addAttr(::new (S.Context) ArmMveAliasAttr(S.Context, AL, Ident)); +} + //===----------------------------------------------------------------------===// // Checker-specific attribute handlers. //===----------------------------------------------------------------------===// @@ -5278,9 +5411,11 @@ UuidAttr *Sema::mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI, if (const auto *UA = D->getAttr<UuidAttr>()) { if (UA->getGuid().equals_lower(Uuid)) return nullptr; - Diag(UA->getLocation(), diag::err_mismatched_uuid); - Diag(CI.getLoc(), diag::note_previous_uuid); - D->dropAttr<UuidAttr>(); + if (!UA->getGuid().empty()) { + Diag(UA->getLocation(), diag::err_mismatched_uuid); + Diag(CI.getLoc(), diag::note_previous_uuid); + D->dropAttr<UuidAttr>(); + } } return ::new (Context) UuidAttr(Context, CI, Uuid); @@ -5342,8 +5477,7 @@ static void handleMSInheritanceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; } MSInheritanceAttr *IA = S.mergeMSInheritanceAttr( - D, AL, /*BestCase=*/true, - (MSInheritanceAttr::Spelling)AL.getSemanticSpelling()); + D, AL, /*BestCase=*/true, (MSInheritanceModel)AL.getSemanticSpelling()); if (IA) { D->addAttr(IA); S.Consumer.AssignInheritanceModel(cast<CXXRecordDecl>(D)); @@ -5620,6 +5754,47 @@ static void handleAVRSignalAttr(Sema &S, Decl *D, const ParsedAttr &AL) { handleSimpleAttribute<AVRSignalAttr>(S, D, AL); } +static void handleBPFPreserveAIRecord(Sema &S, RecordDecl *RD) { + // Add preserve_access_index attribute to all fields and inner records. + for (auto D : RD->decls()) { + if (D->hasAttr<BPFPreserveAccessIndexAttr>()) + continue; + + D->addAttr(BPFPreserveAccessIndexAttr::CreateImplicit(S.Context)); + if (auto *Rec = dyn_cast<RecordDecl>(D)) + handleBPFPreserveAIRecord(S, Rec); + } +} + +static void handleBPFPreserveAccessIndexAttr(Sema &S, Decl *D, + const ParsedAttr &AL) { + auto *Rec = cast<RecordDecl>(D); + handleBPFPreserveAIRecord(S, Rec); + Rec->addAttr(::new (S.Context) BPFPreserveAccessIndexAttr(S.Context, AL)); +} + +static void handleWebAssemblyExportNameAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + if (!isFunctionOrMethod(D)) { + S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type) + << "'export_name'" << ExpectedFunction; + return; + } + + auto *FD = cast<FunctionDecl>(D); + if (FD->isThisDeclarationADefinition()) { + S.Diag(D->getLocation(), diag::err_alias_is_definition) << FD << 0; + return; + } + + StringRef Str; + SourceLocation ArgLoc; + if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc)) + return; + + D->addAttr(::new (S.Context) WebAssemblyExportNameAttr(S.Context, AL, Str)); + D->addAttr(UsedAttr::CreateImplicit(S.Context)); +} + static void handleWebAssemblyImportModuleAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!isFunctionOrMethod(D)) { S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type) @@ -5977,9 +6152,9 @@ static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) { MSInheritanceAttr * Sema::mergeMSInheritanceAttr(Decl *D, const AttributeCommonInfo &CI, bool BestCase, - MSInheritanceAttr::Spelling SemanticSpelling) { + MSInheritanceModel Model) { if (MSInheritanceAttr *IA = D->getAttr<MSInheritanceAttr>()) { - if (IA->getSemanticSpelling() == SemanticSpelling) + if (IA->getInheritanceModel() == Model) return nullptr; Diag(IA->getLocation(), diag::err_mismatched_ms_inheritance) << 1 /*previous declaration*/; @@ -5990,7 +6165,7 @@ Sema::mergeMSInheritanceAttr(Decl *D, const AttributeCommonInfo &CI, auto *RD = cast<CXXRecordDecl>(D); if (RD->hasDefinition()) { if (checkMSInheritanceAttrOnDefinition(RD, CI.getRange(), BestCase, - SemanticSpelling)) { + Model)) { return nullptr; } } else { @@ -6278,6 +6453,45 @@ static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(::new (S.Context) OpenCLAccessAttr(S.Context, AL)); } +static void handleSYCLKernelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + // The 'sycl_kernel' attribute applies only to function templates. + const auto *FD = cast<FunctionDecl>(D); + const FunctionTemplateDecl *FT = FD->getDescribedFunctionTemplate(); + assert(FT && "Function template is expected"); + + // Function template must have at least two template parameters. + const TemplateParameterList *TL = FT->getTemplateParameters(); + if (TL->size() < 2) { + S.Diag(FT->getLocation(), diag::warn_sycl_kernel_num_of_template_params); + return; + } + + // Template parameters must be typenames. + for (unsigned I = 0; I < 2; ++I) { + const NamedDecl *TParam = TL->getParam(I); + if (isa<NonTypeTemplateParmDecl>(TParam)) { + S.Diag(FT->getLocation(), + diag::warn_sycl_kernel_invalid_template_param_type); + return; + } + } + + // Function must have at least one argument. + if (getFunctionOrMethodNumParams(D) != 1) { + S.Diag(FT->getLocation(), diag::warn_sycl_kernel_num_of_function_params); + return; + } + + // Function must return void. + QualType RetTy = getFunctionOrMethodResultType(D); + if (!RetTy->isVoidType()) { + S.Diag(FT->getLocation(), diag::warn_sycl_kernel_return_type); + return; + } + + handleSimpleAttribute<SYCLKernelAttr>(S, D, AL); +} + static void handleDestroyAttr(Sema &S, Decl *D, const ParsedAttr &A) { if (!cast<VarDecl>(D)->hasGlobalStorage()) { S.Diag(D->getLocation(), diag::err_destroy_attr_on_non_static_var) @@ -6406,6 +6620,50 @@ static void handleMSAllocatorAttr(Sema &S, Decl *D, const ParsedAttr &AL) { handleSimpleAttribute<MSAllocatorAttr>(S, D, AL); } +static void handeAcquireHandleAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + if (AL.isUsedAsTypeAttr()) + return; + // Warn if the parameter is definitely not an output parameter. + if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) { + if (PVD->getType()->isIntegerType()) { + S.Diag(AL.getLoc(), diag::err_attribute_output_parameter) + << AL.getRange(); + return; + } + } + StringRef Argument; + if (!S.checkStringLiteralArgumentAttr(AL, 0, Argument)) + return; + D->addAttr(AcquireHandleAttr::Create(S.Context, Argument, AL)); +} + +template<typename Attr> +static void handleHandleAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + StringRef Argument; + if (!S.checkStringLiteralArgumentAttr(AL, 0, Argument)) + return; + D->addAttr(Attr::Create(S.Context, Argument, AL)); +} + +static void handleCFGuardAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + // The guard attribute takes a single identifier argument. + + if (!AL.isArgIdent(0)) { + S.Diag(AL.getLoc(), diag::err_attribute_argument_type) + << AL << AANT_ArgumentIdentifier; + return; + } + + CFGuardAttr::GuardArg Arg; + IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; + if (!CFGuardAttr::ConvertStrToGuardArg(II->getName(), Arg)) { + S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II; + return; + } + + D->addAttr(::new (S.Context) CFGuardAttr(S.Context, AL, Arg)); +} + //===----------------------------------------------------------------------===// // Top Level Sema Entry Points //===----------------------------------------------------------------------===// @@ -6496,6 +6754,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_AVRSignal: handleAVRSignalAttr(S, D, AL); break; + case ParsedAttr::AT_BPFPreserveAccessIndex: + handleBPFPreserveAccessIndexAttr(S, D, AL); + break; + case ParsedAttr::AT_WebAssemblyExportName: + handleWebAssemblyExportNameAttr(S, D, AL); + break; case ParsedAttr::AT_WebAssemblyImportModule: handleWebAssemblyImportModuleAttr(S, D, AL); break; @@ -6578,6 +6842,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_DiagnoseIf: handleDiagnoseIfAttr(S, D, AL); break; + case ParsedAttr::AT_NoBuiltin: + handleNoBuiltinAttr(S, D, AL); + break; case ParsedAttr::AT_ExtVectorType: handleExtVectorTypeAttr(S, D, AL); break; @@ -6599,6 +6866,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_Flatten: handleSimpleAttribute<FlattenAttr>(S, D, AL); break; + case ParsedAttr::AT_SYCLKernel: + handleSYCLKernelAttr(S, D, AL); + break; case ParsedAttr::AT_Format: handleFormatAttr(S, D, AL); break; @@ -6826,6 +7096,13 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_ObjCRootClass: handleSimpleAttribute<ObjCRootClassAttr>(S, D, AL); break; + case ParsedAttr::AT_ObjCDirect: + handleObjCDirectAttr(S, D, AL); + break; + case ParsedAttr::AT_ObjCDirectMembers: + handleObjCDirectMembersAttr(S, D, AL); + handleSimpleAttribute<ObjCDirectMembersAttr>(S, D, AL); + break; case ParsedAttr::AT_ObjCNonLazyClass: handleSimpleAttribute<ObjCNonLazyClassAttr>(S, D, AL); break; @@ -7015,6 +7292,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_AbiTag: handleAbiTagAttr(S, D, AL); break; + case ParsedAttr::AT_CFGuard: + handleCFGuardAttr(S, D, AL); + break; // Thread safety attributes: case ParsedAttr::AT_AssertExclusiveLock: @@ -7135,6 +7415,10 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleXRayLogArgsAttr(S, D, AL); break; + case ParsedAttr::AT_PatchableFunctionEntry: + handlePatchableFunctionEntryAttr(S, D, AL); + break; + // Move semantics attribute. case ParsedAttr::AT_Reinitializes: handleSimpleAttribute<ReinitializesAttr>(S, D, AL); @@ -7160,6 +7444,22 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_MSAllocator: handleMSAllocatorAttr(S, D, AL); break; + + case ParsedAttr::AT_ArmMveAlias: + handleArmMveAliasAttr(S, D, AL); + break; + + case ParsedAttr::AT_AcquireHandle: + handeAcquireHandleAttr(S, D, AL); + break; + + case ParsedAttr::AT_ReleaseHandle: + handleHandleAttr<ReleaseHandleAttr>(S, D, AL); + break; + + case ParsedAttr::AT_UseHandle: + handleHandleAttr<UseHandleAttr>(S, D, AL); + break; } } @@ -7238,7 +7538,8 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, } } -// Helper for delayed processing TransparentUnion attribute. +// Helper for delayed processing TransparentUnion or BPFPreserveAccessIndexAttr +// attribute. void Sema::ProcessDeclAttributeDelayed(Decl *D, const ParsedAttributesView &AttrList) { for (const ParsedAttr &AL : AttrList) @@ -7246,6 +7547,11 @@ void Sema::ProcessDeclAttributeDelayed(Decl *D, handleTransparentUnionAttr(*this, D, AL); break; } + + // For BPFPreserveAccessIndexAttr, we want to populate the attributes + // to fields and inner records as well. + if (D && D->hasAttr<BPFPreserveAccessIndexAttr>()) + handleBPFPreserveAIRecord(*this, cast<RecordDecl>(D)); } // Annotation attributes are the only attributes allowed after an access @@ -7308,7 +7614,8 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II, NewFD = FunctionDecl::Create( FD->getASTContext(), FD->getDeclContext(), Loc, Loc, DeclarationName(II), FD->getType(), FD->getTypeSourceInfo(), SC_None, - false /*isInlineSpecified*/, FD->hasPrototype(), CSK_unspecified); + false /*isInlineSpecified*/, FD->hasPrototype(), CSK_unspecified, + FD->getTrailingRequiresClause()); NewD = NewFD; if (FD->getQualifier()) |