Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:59

0001 //===----- Attr.h --- Helper functions for attribute handling in Sema -----===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 //  This file provides helpers for Sema functions that handle attributes.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_CLANG_SEMA_ATTR_H
0014 #define LLVM_CLANG_SEMA_ATTR_H
0015 
0016 #include "clang/AST/Attr.h"
0017 #include "clang/AST/Decl.h"
0018 #include "clang/AST/DeclBase.h"
0019 #include "clang/AST/DeclCXX.h"
0020 #include "clang/AST/DeclObjC.h"
0021 #include "clang/AST/Type.h"
0022 #include "clang/Basic/AttributeCommonInfo.h"
0023 #include "clang/Basic/DiagnosticSema.h"
0024 #include "clang/Basic/SourceLocation.h"
0025 #include "clang/Sema/ParsedAttr.h"
0026 #include "clang/Sema/SemaBase.h"
0027 #include "llvm/Support/Casting.h"
0028 
0029 namespace clang {
0030 
0031 /// isFuncOrMethodForAttrSubject - Return true if the given decl has function
0032 /// type (function or function-typed variable) or an Objective-C
0033 /// method.
0034 inline bool isFuncOrMethodForAttrSubject(const Decl *D) {
0035   return (D->getFunctionType() != nullptr) || llvm::isa<ObjCMethodDecl>(D);
0036 }
0037 
0038 /// Return true if the given decl has function type (function or
0039 /// function-typed variable) or an Objective-C method or a block.
0040 inline bool isFunctionOrMethodOrBlockForAttrSubject(const Decl *D) {
0041   return isFuncOrMethodForAttrSubject(D) || llvm::isa<BlockDecl>(D);
0042 }
0043 
0044 /// Return true if the given decl has a declarator that should have
0045 /// been processed by Sema::GetTypeForDeclarator.
0046 inline bool hasDeclarator(const Decl *D) {
0047   // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl.
0048   return isa<DeclaratorDecl>(D) || isa<BlockDecl>(D) ||
0049          isa<TypedefNameDecl>(D) || isa<ObjCPropertyDecl>(D);
0050 }
0051 
0052 /// hasFunctionProto - Return true if the given decl has a argument
0053 /// information. This decl should have already passed
0054 /// isFuncOrMethodForAttrSubject or isFunctionOrMethodOrBlockForAttrSubject.
0055 inline bool hasFunctionProto(const Decl *D) {
0056   if (const FunctionType *FnTy = D->getFunctionType())
0057     return isa<FunctionProtoType>(FnTy);
0058   return isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D);
0059 }
0060 
0061 /// getFunctionOrMethodNumParams - Return number of function or method
0062 /// parameters. It is an error to call this on a K&R function (use
0063 /// hasFunctionProto first).
0064 inline unsigned getFunctionOrMethodNumParams(const Decl *D) {
0065   if (const FunctionType *FnTy = D->getFunctionType())
0066     return cast<FunctionProtoType>(FnTy)->getNumParams();
0067   if (const auto *BD = dyn_cast<BlockDecl>(D))
0068     return BD->getNumParams();
0069   return cast<ObjCMethodDecl>(D)->param_size();
0070 }
0071 
0072 inline const ParmVarDecl *getFunctionOrMethodParam(const Decl *D,
0073                                                    unsigned Idx) {
0074   if (const auto *FD = dyn_cast<FunctionDecl>(D))
0075     return FD->getParamDecl(Idx);
0076   if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
0077     return MD->getParamDecl(Idx);
0078   if (const auto *BD = dyn_cast<BlockDecl>(D))
0079     return BD->getParamDecl(Idx);
0080   return nullptr;
0081 }
0082 
0083 inline QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) {
0084   if (const FunctionType *FnTy = D->getFunctionType())
0085     return cast<FunctionProtoType>(FnTy)->getParamType(Idx);
0086   if (const auto *BD = dyn_cast<BlockDecl>(D))
0087     return BD->getParamDecl(Idx)->getType();
0088 
0089   return cast<ObjCMethodDecl>(D)->parameters()[Idx]->getType();
0090 }
0091 
0092 inline SourceRange getFunctionOrMethodParamRange(const Decl *D, unsigned Idx) {
0093   if (auto *PVD = getFunctionOrMethodParam(D, Idx))
0094     return PVD->getSourceRange();
0095   return SourceRange();
0096 }
0097 
0098 inline QualType getFunctionOrMethodResultType(const Decl *D) {
0099   if (const FunctionType *FnTy = D->getFunctionType())
0100     return FnTy->getReturnType();
0101   return cast<ObjCMethodDecl>(D)->getReturnType();
0102 }
0103 
0104 inline SourceRange getFunctionOrMethodResultSourceRange(const Decl *D) {
0105   if (const auto *FD = dyn_cast<FunctionDecl>(D))
0106     return FD->getReturnTypeSourceRange();
0107   if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
0108     return MD->getReturnTypeSourceRange();
0109   return SourceRange();
0110 }
0111 
0112 inline bool isFunctionOrMethodVariadic(const Decl *D) {
0113   if (const FunctionType *FnTy = D->getFunctionType())
0114     return cast<FunctionProtoType>(FnTy)->isVariadic();
0115   if (const auto *BD = dyn_cast<BlockDecl>(D))
0116     return BD->isVariadic();
0117   return cast<ObjCMethodDecl>(D)->isVariadic();
0118 }
0119 
0120 inline bool isInstanceMethod(const Decl *D) {
0121   if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(D))
0122     return MethodDecl->isInstance();
0123   return false;
0124 }
0125 
0126 /// Diagnose mutually exclusive attributes when present on a given
0127 /// declaration. Returns true if diagnosed.
0128 template <typename AttrTy>
0129 bool checkAttrMutualExclusion(SemaBase &S, Decl *D, const ParsedAttr &AL) {
0130   if (const auto *A = D->getAttr<AttrTy>()) {
0131     S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
0132         << AL << A
0133         << (AL.isRegularKeywordAttribute() || A->isRegularKeywordAttribute());
0134     S.Diag(A->getLocation(), diag::note_conflicting_attribute);
0135     return true;
0136   }
0137   return false;
0138 }
0139 
0140 template <typename AttrTy>
0141 bool checkAttrMutualExclusion(SemaBase &S, Decl *D, const Attr &AL) {
0142   if (const auto *A = D->getAttr<AttrTy>()) {
0143     S.Diag(AL.getLocation(), diag::err_attributes_are_not_compatible)
0144         << &AL << A
0145         << (AL.isRegularKeywordAttribute() || A->isRegularKeywordAttribute());
0146     Diag(A->getLocation(), diag::note_conflicting_attribute);
0147     return true;
0148   }
0149   return false;
0150 }
0151 
0152 template <typename... DiagnosticArgs>
0153 const SemaBase::SemaDiagnosticBuilder &
0154 appendDiagnostics(const SemaBase::SemaDiagnosticBuilder &Bldr) {
0155   return Bldr;
0156 }
0157 
0158 template <typename T, typename... DiagnosticArgs>
0159 const SemaBase::SemaDiagnosticBuilder &
0160 appendDiagnostics(const SemaBase::SemaDiagnosticBuilder &Bldr, T &&ExtraArg,
0161                   DiagnosticArgs &&...ExtraArgs) {
0162   return appendDiagnostics(Bldr << std::forward<T>(ExtraArg),
0163                            std::forward<DiagnosticArgs>(ExtraArgs)...);
0164 }
0165 
0166 /// Applies the given attribute to the Decl without performing any
0167 /// additional semantic checking.
0168 template <typename AttrType>
0169 void handleSimpleAttribute(SemaBase &S, Decl *D,
0170                            const AttributeCommonInfo &CI) {
0171   D->addAttr(::new (S.getASTContext()) AttrType(S.getASTContext(), CI));
0172 }
0173 
0174 /// Add an attribute @c AttrType to declaration @c D, provided that
0175 /// @c PassesCheck is true.
0176 /// Otherwise, emit diagnostic @c DiagID, passing in all parameters
0177 /// specified in @c ExtraArgs.
0178 template <typename AttrType, typename... DiagnosticArgs>
0179 void handleSimpleAttributeOrDiagnose(SemaBase &S, Decl *D,
0180                                      const AttributeCommonInfo &CI,
0181                                      bool PassesCheck, unsigned DiagID,
0182                                      DiagnosticArgs &&...ExtraArgs) {
0183   if (!PassesCheck) {
0184     SemaBase::SemaDiagnosticBuilder DB = S.Diag(D->getBeginLoc(), DiagID);
0185     appendDiagnostics(DB, std::forward<DiagnosticArgs>(ExtraArgs)...);
0186     return;
0187   }
0188   handleSimpleAttribute<AttrType>(S, D, CI);
0189 }
0190 
0191 } // namespace clang
0192 #endif // LLVM_CLANG_SEMA_ATTR_H