diff options
Diffstat (limited to 'clang/lib/Sema/ParsedAttr.cpp')
-rw-r--r-- | clang/lib/Sema/ParsedAttr.cpp | 86 |
1 files changed, 51 insertions, 35 deletions
diff --git a/clang/lib/Sema/ParsedAttr.cpp b/clang/lib/Sema/ParsedAttr.cpp index 5d0a734f237a..3ef8498baffd 100644 --- a/clang/lib/Sema/ParsedAttr.cpp +++ b/clang/lib/Sema/ParsedAttr.cpp @@ -19,12 +19,15 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/ManagedStatic.h" #include <cassert> #include <cstddef> #include <utility> using namespace clang; +LLVM_INSTANTIATE_REGISTRY(ParsedAttrInfoRegistry) + IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc, IdentifierInfo *Ident) { IdentifierLoc *Result = new (Ctx) IdentifierLoc; @@ -100,47 +103,60 @@ void AttributePool::takePool(AttributePool &pool) { pool.Attrs.clear(); } -struct ParsedAttrInfo { - unsigned NumArgs : 4; - unsigned OptArgs : 4; - unsigned HasCustomParsing : 1; - unsigned IsTargetSpecific : 1; - unsigned IsType : 1; - unsigned IsStmt : 1; - unsigned IsKnownToGCC : 1; - unsigned IsSupportedByPragmaAttribute : 1; - - bool (*DiagAppertainsToDecl)(Sema &S, const ParsedAttr &Attr, const Decl *); - bool (*DiagLangOpts)(Sema &S, const ParsedAttr &Attr); - bool (*ExistsInTarget)(const TargetInfo &Target); - unsigned (*SpellingIndexToSemanticSpelling)(const ParsedAttr &Attr); - void (*GetPragmaAttributeMatchRules)( - llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules, - const LangOptions &LangOpts); -}; - namespace { #include "clang/Sema/AttrParsedAttrImpl.inc" } // namespace -static const ParsedAttrInfo &getInfo(const ParsedAttr &A) { - return AttrInfoMap[A.getKind()]; +const ParsedAttrInfo &ParsedAttrInfo::get(const AttributeCommonInfo &A) { + // If we have a ParsedAttrInfo for this ParsedAttr then return that. + if ((size_t)A.getParsedKind() < llvm::array_lengthof(AttrInfoMap)) + return *AttrInfoMap[A.getParsedKind()]; + + // If this is an ignored attribute then return an appropriate ParsedAttrInfo. + static const ParsedAttrInfo IgnoredParsedAttrInfo( + AttributeCommonInfo::IgnoredAttribute); + if (A.getParsedKind() == AttributeCommonInfo::IgnoredAttribute) + return IgnoredParsedAttrInfo; + + // Otherwise this may be an attribute defined by a plugin. First instantiate + // all plugin attributes if we haven't already done so. + static llvm::ManagedStatic<std::list<std::unique_ptr<ParsedAttrInfo>>> + PluginAttrInstances; + if (PluginAttrInstances->empty()) + for (auto It : ParsedAttrInfoRegistry::entries()) + PluginAttrInstances->emplace_back(It.instantiate()); + + // Search for a ParsedAttrInfo whose name and syntax match. + std::string FullName = A.getNormalizedFullName(); + AttributeCommonInfo::Syntax SyntaxUsed = A.getSyntax(); + if (SyntaxUsed == AttributeCommonInfo::AS_ContextSensitiveKeyword) + SyntaxUsed = AttributeCommonInfo::AS_Keyword; + + for (auto &Ptr : *PluginAttrInstances) + for (auto &S : Ptr->Spellings) + if (S.Syntax == SyntaxUsed && S.NormalizedFullName == FullName) + return *Ptr; + + // If we failed to find a match then return a default ParsedAttrInfo. + static const ParsedAttrInfo DefaultParsedAttrInfo( + AttributeCommonInfo::UnknownAttribute); + return DefaultParsedAttrInfo; } -unsigned ParsedAttr::getMinArgs() const { return getInfo(*this).NumArgs; } +unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; } unsigned ParsedAttr::getMaxArgs() const { - return getMinArgs() + getInfo(*this).OptArgs; + return getMinArgs() + getInfo().OptArgs; } bool ParsedAttr::hasCustomParsing() const { - return getInfo(*this).HasCustomParsing; + return getInfo().HasCustomParsing; } bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const { - return getInfo(*this).DiagAppertainsToDecl(S, *this, D); + return getInfo().diagAppertainsToDecl(S, *this, D); } bool ParsedAttr::appliesToDecl(const Decl *D, @@ -152,33 +168,33 @@ void ParsedAttr::getMatchRules( const LangOptions &LangOpts, SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules) const { - return getInfo(*this).GetPragmaAttributeMatchRules(MatchRules, LangOpts); + return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts); } bool ParsedAttr::diagnoseLangOpts(Sema &S) const { - return getInfo(*this).DiagLangOpts(S, *this); + return getInfo().diagLangOpts(S, *this); } bool ParsedAttr::isTargetSpecificAttr() const { - return getInfo(*this).IsTargetSpecific; + return getInfo().IsTargetSpecific; } -bool ParsedAttr::isTypeAttr() const { return getInfo(*this).IsType; } +bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; } -bool ParsedAttr::isStmtAttr() const { return getInfo(*this).IsStmt; } +bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; } bool ParsedAttr::existsInTarget(const TargetInfo &Target) const { - return getInfo(*this).ExistsInTarget(Target); + return getInfo().existsInTarget(Target); } -bool ParsedAttr::isKnownToGCC() const { return getInfo(*this).IsKnownToGCC; } +bool ParsedAttr::isKnownToGCC() const { return getInfo().IsKnownToGCC; } bool ParsedAttr::isSupportedByPragmaAttribute() const { - return getInfo(*this).IsSupportedByPragmaAttribute; + return getInfo().IsSupportedByPragmaAttribute; } unsigned ParsedAttr::getSemanticSpelling() const { - return getInfo(*this).SpellingIndexToSemanticSpelling(*this); + return getInfo().spellingIndexToSemanticSpelling(*this); } bool ParsedAttr::hasVariadicArg() const { @@ -186,5 +202,5 @@ bool ParsedAttr::hasVariadicArg() const { // claim that as being variadic. If we someday get an attribute that // legitimately bumps up against that maximum, we can use another bit to track // whether it's truly variadic or not. - return getInfo(*this).OptArgs == 15; + return getInfo().OptArgs == 15; } |