summaryrefslogtreecommitdiff
path: root/clang/lib/Sema/ParsedAttr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/ParsedAttr.cpp')
-rw-r--r--clang/lib/Sema/ParsedAttr.cpp86
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;
}