blob: 537d8f3391d5898705317fd5637c450ec8c00625 [file] [log] [blame]
//===- ParsedAttrInfo.h - Info needed to parse an attribute -----*- C++ -*-===//
//
// 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 defines the ParsedAttrInfo class, which dictates how to
// parse an attribute. This class is the one that plugins derive to
// define a new attribute.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_PARSEDATTRINFO_H
#define LLVM_CLANG_BASIC_PARSEDATTRINFO_H
#include "clang/Basic/AttrSubjectMatchRules.h"
#include "clang/Basic/AttributeCommonInfo.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Registry.h"
#include <climits>
#include <list>
namespace clang {
class Decl;
class LangOptions;
class ParsedAttr;
class Sema;
class Stmt;
class TargetInfo;
struct ParsedAttrInfo {
/// Corresponds to the Kind enum.
LLVM_PREFERRED_TYPE(AttributeCommonInfo::Kind)
unsigned AttrKind : 16;
/// The number of required arguments of this attribute.
unsigned NumArgs : 4;
/// The number of optional arguments of this attributes.
unsigned OptArgs : 4;
/// The number of non-fake arguments specified in the attribute definition.
unsigned NumArgMembers : 4;
/// True if the parsing does not match the semantic content.
LLVM_PREFERRED_TYPE(bool)
unsigned HasCustomParsing : 1;
// True if this attribute accepts expression parameter pack expansions.
LLVM_PREFERRED_TYPE(bool)
unsigned AcceptsExprPack : 1;
/// True if this attribute is only available for certain targets.
LLVM_PREFERRED_TYPE(bool)
unsigned IsTargetSpecific : 1;
/// True if this attribute applies to types.
LLVM_PREFERRED_TYPE(bool)
unsigned IsType : 1;
/// True if this attribute applies to statements.
LLVM_PREFERRED_TYPE(bool)
unsigned IsStmt : 1;
/// True if this attribute has any spellings that are known to gcc.
LLVM_PREFERRED_TYPE(bool)
unsigned IsKnownToGCC : 1;
/// True if this attribute is supported by #pragma clang attribute.
LLVM_PREFERRED_TYPE(bool)
unsigned IsSupportedByPragmaAttribute : 1;
/// The syntaxes supported by this attribute and how they're spelled.
struct Spelling {
AttributeCommonInfo::Syntax Syntax;
const char *NormalizedFullName;
};
ArrayRef<Spelling> Spellings;
// The names of the known arguments of this attribute.
ArrayRef<const char *> ArgNames;
protected:
constexpr ParsedAttrInfo(AttributeCommonInfo::Kind AttrKind =
AttributeCommonInfo::NoSemaHandlerAttribute)
: AttrKind(AttrKind), NumArgs(0), OptArgs(0), NumArgMembers(0),
HasCustomParsing(0), AcceptsExprPack(0), IsTargetSpecific(0), IsType(0),
IsStmt(0), IsKnownToGCC(0), IsSupportedByPragmaAttribute(0) {}
constexpr ParsedAttrInfo(AttributeCommonInfo::Kind AttrKind, unsigned NumArgs,
unsigned OptArgs, unsigned NumArgMembers,
unsigned HasCustomParsing, unsigned AcceptsExprPack,
unsigned IsTargetSpecific, unsigned IsType,
unsigned IsStmt, unsigned IsKnownToGCC,
unsigned IsSupportedByPragmaAttribute,
ArrayRef<Spelling> Spellings,
ArrayRef<const char *> ArgNames)
: AttrKind(AttrKind), NumArgs(NumArgs), OptArgs(OptArgs),
NumArgMembers(NumArgMembers), HasCustomParsing(HasCustomParsing),
AcceptsExprPack(AcceptsExprPack), IsTargetSpecific(IsTargetSpecific),
IsType(IsType), IsStmt(IsStmt), IsKnownToGCC(IsKnownToGCC),
IsSupportedByPragmaAttribute(IsSupportedByPragmaAttribute),
Spellings(Spellings), ArgNames(ArgNames) {}
public:
virtual ~ParsedAttrInfo() = default;
/// Check if this attribute has specified spelling.
bool hasSpelling(AttributeCommonInfo::Syntax Syntax, StringRef Name) const {
return llvm::any_of(Spellings, [&](const Spelling &S) {
return (S.Syntax == Syntax && S.NormalizedFullName == Name);
});
}
/// Check if this attribute appertains to D, and issue a diagnostic if not.
virtual bool diagAppertainsToDecl(Sema &S, const ParsedAttr &Attr,
const Decl *D) const {
return true;
}
/// Check if this attribute appertains to St, and issue a diagnostic if not.
virtual bool diagAppertainsToStmt(Sema &S, const ParsedAttr &Attr,
const Stmt *St) const {
return true;
}
/// Check if the given attribute is mutually exclusive with other attributes
/// already applied to the given declaration.
virtual bool diagMutualExclusion(Sema &S, const ParsedAttr &A,
const Decl *D) const {
return true;
}
/// Check if this attribute is allowed by the language we are compiling.
virtual bool acceptsLangOpts(const LangOptions &LO) const { return true; }
/// Check if this attribute is allowed when compiling for the given target.
virtual bool existsInTarget(const TargetInfo &Target) const { return true; }
/// Check if this attribute's spelling is allowed when compiling for the given
/// target.
virtual bool spellingExistsInTarget(const TargetInfo &Target,
const unsigned SpellingListIndex) const {
return true;
}
/// Convert the spelling index of Attr to a semantic spelling enum value.
virtual unsigned
spellingIndexToSemanticSpelling(const ParsedAttr &Attr) const {
return UINT_MAX;
}
/// Returns true if the specified parameter index for this attribute in
/// Attr.td is an ExprArgument or VariadicExprArgument, or a subclass thereof;
/// returns false otherwise.
virtual bool isParamExpr(size_t N) const { return false; }
/// Populate Rules with the match rules of this attribute.
virtual void getPragmaAttributeMatchRules(
llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules,
const LangOptions &LangOpts) const {}
enum AttrHandling { NotHandled, AttributeApplied, AttributeNotApplied };
/// If this ParsedAttrInfo knows how to handle this ParsedAttr applied to this
/// Decl then do so and return either AttributeApplied if it was applied or
/// AttributeNotApplied if it wasn't. Otherwise return NotHandled.
virtual AttrHandling handleDeclAttribute(Sema &S, Decl *D,
const ParsedAttr &Attr) const {
return NotHandled;
}
static const ParsedAttrInfo &get(const AttributeCommonInfo &A);
static ArrayRef<const ParsedAttrInfo *> getAllBuiltin();
};
typedef llvm::Registry<ParsedAttrInfo> ParsedAttrInfoRegistry;
const std::list<std::unique_ptr<ParsedAttrInfo>> &getAttributePluginInstances();
} // namespace clang
#endif // LLVM_CLANG_BASIC_PARSEDATTRINFO_H