//===----- Attr.h --- Helper functions for attribute handling in Sema -----===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file provides helpers for Sema functions that handle attributes. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_SEMA_ATTR_H #define LLVM_CLANG_SEMA_ATTR_H #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Type.h" #include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/SourceLocation.h" #include "clang/Sema/ParsedAttr.h" #include "clang/Sema/SemaBase.h" #include "llvm/Support/Casting.h" namespace clang { /// isFuncOrMethodForAttrSubject - Return true if the given decl has function /// type (function or function-typed variable) or an Objective-C /// method. inline bool isFuncOrMethodForAttrSubject(const Decl *D) { return (D->getFunctionType() != nullptr) || llvm::isa(D); } /// Return true if the given decl has function type (function or /// function-typed variable) or an Objective-C method or a block. inline bool isFunctionOrMethodOrBlockForAttrSubject(const Decl *D) { return isFuncOrMethodForAttrSubject(D) || llvm::isa(D); } /// Return true if the given decl has a declarator that should have /// been processed by Sema::GetTypeForDeclarator. inline bool hasDeclarator(const Decl *D) { // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl. return isa(D) || isa(D) || isa(D) || isa(D); } /// hasFunctionProto - Return true if the given decl has a argument /// information. This decl should have already passed /// isFuncOrMethodForAttrSubject or isFunctionOrMethodOrBlockForAttrSubject. inline bool hasFunctionProto(const Decl *D) { if (const FunctionType *FnTy = D->getFunctionType()) return isa(FnTy); return isa(D) || isa(D); } /// getFunctionOrMethodNumParams - Return number of function or method /// parameters. It is an error to call this on a K&R function (use /// hasFunctionProto first). inline unsigned getFunctionOrMethodNumParams(const Decl *D) { if (const FunctionType *FnTy = D->getFunctionType()) return cast(FnTy)->getNumParams(); if (const auto *BD = dyn_cast(D)) return BD->getNumParams(); return cast(D)->param_size(); } inline const ParmVarDecl *getFunctionOrMethodParam(const Decl *D, unsigned Idx) { if (const auto *FD = dyn_cast(D)) return FD->getParamDecl(Idx); if (const auto *MD = dyn_cast(D)) return MD->getParamDecl(Idx); if (const auto *BD = dyn_cast(D)) return BD->getParamDecl(Idx); return nullptr; } inline QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) { if (const FunctionType *FnTy = D->getFunctionType()) return cast(FnTy)->getParamType(Idx); if (const auto *BD = dyn_cast(D)) return BD->getParamDecl(Idx)->getType(); return cast(D)->parameters()[Idx]->getType(); } inline SourceRange getFunctionOrMethodParamRange(const Decl *D, unsigned Idx) { if (auto *PVD = getFunctionOrMethodParam(D, Idx)) return PVD->getSourceRange(); return SourceRange(); } inline QualType getFunctionOrMethodResultType(const Decl *D) { if (const FunctionType *FnTy = D->getFunctionType()) return FnTy->getReturnType(); return cast(D)->getReturnType(); } inline SourceRange getFunctionOrMethodResultSourceRange(const Decl *D) { if (const auto *FD = dyn_cast(D)) return FD->getReturnTypeSourceRange(); if (const auto *MD = dyn_cast(D)) return MD->getReturnTypeSourceRange(); return SourceRange(); } inline bool isFunctionOrMethodVariadic(const Decl *D) { if (const FunctionType *FnTy = D->getFunctionType()) return cast(FnTy)->isVariadic(); if (const auto *BD = dyn_cast(D)) return BD->isVariadic(); return cast(D)->isVariadic(); } inline bool isInstanceMethod(const Decl *D) { if (const auto *MethodDecl = dyn_cast(D)) return MethodDecl->isInstance(); return false; } /// Diagnose mutually exclusive attributes when present on a given /// declaration. Returns true if diagnosed. template bool checkAttrMutualExclusion(SemaBase &S, Decl *D, const ParsedAttr &AL) { if (const auto *A = D->getAttr()) { S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << A << (AL.isRegularKeywordAttribute() || A->isRegularKeywordAttribute()); S.Diag(A->getLocation(), diag::note_conflicting_attribute); return true; } return false; } template bool checkAttrMutualExclusion(SemaBase &S, Decl *D, const Attr &AL) { if (const auto *A = D->getAttr()) { S.Diag(AL.getLocation(), diag::err_attributes_are_not_compatible) << &AL << A << (AL.isRegularKeywordAttribute() || A->isRegularKeywordAttribute()); Diag(A->getLocation(), diag::note_conflicting_attribute); return true; } return false; } template const SemaBase::SemaDiagnosticBuilder & appendDiagnostics(const SemaBase::SemaDiagnosticBuilder &Bldr) { return Bldr; } template const SemaBase::SemaDiagnosticBuilder & appendDiagnostics(const SemaBase::SemaDiagnosticBuilder &Bldr, T &&ExtraArg, DiagnosticArgs &&...ExtraArgs) { return appendDiagnostics(Bldr << std::forward(ExtraArg), std::forward(ExtraArgs)...); } /// Applies the given attribute to the Decl without performing any /// additional semantic checking. template void handleSimpleAttribute(SemaBase &S, Decl *D, const AttributeCommonInfo &CI) { D->addAttr(::new (S.getASTContext()) AttrType(S.getASTContext(), CI)); } /// Add an attribute @c AttrType to declaration @c D, provided that /// @c PassesCheck is true. /// Otherwise, emit diagnostic @c DiagID, passing in all parameters /// specified in @c ExtraArgs. template void handleSimpleAttributeOrDiagnose(SemaBase &S, Decl *D, const AttributeCommonInfo &CI, bool PassesCheck, unsigned DiagID, DiagnosticArgs &&...ExtraArgs) { if (!PassesCheck) { SemaBase::SemaDiagnosticBuilder DB = S.Diag(D->getBeginLoc(), DiagID); appendDiagnostics(DB, std::forward(ExtraArgs)...); return; } handleSimpleAttribute(S, D, CI); } } // namespace clang #endif // LLVM_CLANG_SEMA_ATTR_H