diff options
author | Alex Lorenz <arphaman@gmail.com> | 2017-04-19 15:52:11 +0000 |
---|---|---|
committer | Alex Lorenz <arphaman@gmail.com> | 2017-04-19 15:52:11 +0000 |
commit | 9192aede9d38af6d44143c44c8682381aec246d4 (patch) | |
tree | f1c505665ca478915975b852813c950dda4aacee /utils | |
parent | a8d0898b8748814196954c708a555897d66bacb5 (diff) |
Add #pragma clang attribute support to the external_source_symbol attribute
Prior to this commit the external_source_symbol attribute wasn't supported by
#pragma clang attribute for the following two reasons:
- The Named attribute subject hasn't been supported by TableGen.
- There was no way to specify a subject match rule for #pragma clang attribute
that could operate on a set of attribute subjects (e.g. the ones that derive
from NamedDecl).
This commit fixes the two issues and thus adds external_source_symbol support to
#pragma clang attribute.
rdar://31169028
Differential Revision: https://reviews.llvm.org/D32176
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@300712 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r-- | utils/TableGen/ClangAttrEmitter.cpp | 137 |
1 files changed, 113 insertions, 24 deletions
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index 97b3c40590..9814456753 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -1611,7 +1611,36 @@ const char *AttributeSubjectMatchRule::EnumName = "attr::SubjectMatchRule"; struct PragmaClangAttributeSupport { std::vector<AttributeSubjectMatchRule> Rules; - llvm::DenseMap<const Record *, AttributeSubjectMatchRule> SubjectsToRules; + + class RuleOrAggregateRuleSet { + std::vector<AttributeSubjectMatchRule> Rules; + bool IsRule; + RuleOrAggregateRuleSet(ArrayRef<AttributeSubjectMatchRule> Rules, + bool IsRule) + : Rules(Rules), IsRule(IsRule) {} + + public: + bool isRule() const { return IsRule; } + + const AttributeSubjectMatchRule &getRule() const { + assert(IsRule && "not a rule!"); + return Rules[0]; + } + + ArrayRef<AttributeSubjectMatchRule> getAggregateRuleSet() const { + return Rules; + } + + static RuleOrAggregateRuleSet + getRule(const AttributeSubjectMatchRule &Rule) { + return RuleOrAggregateRuleSet(Rule, /*IsRule=*/true); + } + static RuleOrAggregateRuleSet + getAggregateRuleSet(ArrayRef<AttributeSubjectMatchRule> Rules) { + return RuleOrAggregateRuleSet(Rules, /*IsRule=*/false); + } + }; + llvm::DenseMap<const Record *, RuleOrAggregateRuleSet> SubjectsToRules; PragmaClangAttributeSupport(RecordKeeper &Records); @@ -1626,6 +1655,15 @@ struct PragmaClangAttributeSupport { } // end anonymous namespace +static bool doesDeclDeriveFrom(const Record *D, const Record *Base) { + const Record *CurrentBase = D->getValueAsDef("Base"); + if (!CurrentBase) + return false; + if (CurrentBase == Base) + return true; + return doesDeclDeriveFrom(CurrentBase, Base); +} + PragmaClangAttributeSupport::PragmaClangAttributeSupport( RecordKeeper &Records) { std::vector<Record *> MetaSubjects = @@ -1638,7 +1676,11 @@ PragmaClangAttributeSupport::PragmaClangAttributeSupport( SubjectContainer->getValueAsListOfDefs("Subjects"); for (const auto *Subject : ApplicableSubjects) { bool Inserted = - SubjectsToRules.try_emplace(Subject, MetaSubject, Constraint).second; + SubjectsToRules + .try_emplace(Subject, RuleOrAggregateRuleSet::getRule( + AttributeSubjectMatchRule(MetaSubject, + Constraint))) + .second; if (!Inserted) { PrintFatalError("Attribute subject match rules should not represent" "same attribute subjects."); @@ -1652,6 +1694,37 @@ PragmaClangAttributeSupport::PragmaClangAttributeSupport( for (const auto *Constraint : Constraints) MapFromSubjectsToRules(Constraint, MetaSubject, Constraint); } + + std::vector<Record *> Aggregates = + Records.getAllDerivedDefinitions("AttrSubjectMatcherAggregateRule"); + std::vector<Record *> DeclNodes = Records.getAllDerivedDefinitions("DDecl"); + for (const auto *Aggregate : Aggregates) { + Record *SubjectDecl = Aggregate->getValueAsDef("Subject"); + + // Gather sub-classes of the aggregate subject that act as attribute + // subject rules. + std::vector<AttributeSubjectMatchRule> Rules; + for (const auto *D : DeclNodes) { + if (doesDeclDeriveFrom(D, SubjectDecl)) { + auto It = SubjectsToRules.find(D); + if (It == SubjectsToRules.end()) + continue; + if (!It->second.isRule() || It->second.getRule().isSubRule()) + continue; // Assume that the rule will be included as well. + Rules.push_back(It->second.getRule()); + } + } + + bool Inserted = + SubjectsToRules + .try_emplace(SubjectDecl, + RuleOrAggregateRuleSet::getAggregateRuleSet(Rules)) + .second; + if (!Inserted) { + PrintFatalError("Attribute subject match rules should not represent" + "same attribute subjects."); + } + } } static PragmaClangAttributeSupport & @@ -1738,24 +1811,25 @@ PragmaClangAttributeSupport::generateStrictConformsTo(const Record &Attr, auto It = SubjectsToRules.find(Subject); assert(It != SubjectsToRules.end() && "This attribute is unsupported by #pragma clang attribute"); - AttributeSubjectMatchRule Rule = It->getSecond(); - // The rule might be language specific, so only subtract it from the given - // rules if the specific language options are specified. - std::vector<Record *> LangOpts = Rule.getLangOpts(); - SS << " MatchRules.push_back(std::make_pair(" << Rule.getEnumValue() - << ", /*IsSupported=*/"; - if (!LangOpts.empty()) { - for (auto I = LangOpts.begin(), E = LangOpts.end(); I != E; ++I) { - std::string Part = (*I)->getValueAsString("Name"); - if ((*I)->getValueAsBit("Negated")) - SS << "!"; - SS << "LangOpts." + Part; - if (I + 1 != E) - SS << " || "; - } - } else - SS << "true"; - SS << "));\n"; + for (const auto &Rule : It->getSecond().getAggregateRuleSet()) { + // The rule might be language specific, so only subtract it from the given + // rules if the specific language options are specified. + std::vector<Record *> LangOpts = Rule.getLangOpts(); + SS << " MatchRules.push_back(std::make_pair(" << Rule.getEnumValue() + << ", /*IsSupported=*/"; + if (!LangOpts.empty()) { + for (auto I = LangOpts.begin(), E = LangOpts.end(); I != E; ++I) { + std::string Part = (*I)->getValueAsString("Name"); + if ((*I)->getValueAsBit("Negated")) + SS << "!"; + SS << "LangOpts." + Part; + if (I + 1 != E) + SS << " || "; + } + } else + SS << "true"; + SS << "));\n"; + } } SS << "}\n\n"; OS << SS.str(); @@ -2937,7 +3011,8 @@ static std::string CalculateDiagnostic(const Record &S) { Field = 1U << 12, CXXMethod = 1U << 13, ObjCProtocol = 1U << 14, - Enum = 1U << 15 + Enum = 1U << 15, + Named = 1U << 16, }; uint32_t SubMask = 0; @@ -2972,6 +3047,7 @@ static std::string CalculateDiagnostic(const Record &S) { .Case("Field", Field) .Case("CXXMethod", CXXMethod) .Case("Enum", Enum) + .Case("Named", Named) .Default(0); if (!V) { // Something wasn't in our mapping, so be helpful and let the developer @@ -3030,6 +3106,9 @@ static std::string CalculateDiagnostic(const Record &S) { case ObjCProtocol | ObjCInterface: return "ExpectedObjectiveCInterfaceOrProtocol"; case Field | Var: return "ExpectedFieldOrGlobalVar"; + + case Named: + return "ExpectedNamedDecl"; } PrintFatalError(S.getLoc(), @@ -3754,9 +3833,19 @@ void EmitTestPragmaAttributeSupportedAttributes(RecordKeeper &Records, for (const auto &Subject : llvm::enumerate(Subjects)) { if (Subject.index()) OS << ", "; - OS << Support.SubjectsToRules.find(Subject.value()) - ->getSecond() - .getEnumValueName(); + PragmaClangAttributeSupport::RuleOrAggregateRuleSet &RuleSet = + Support.SubjectsToRules.find(Subject.value())->getSecond(); + if (RuleSet.isRule()) { + OS << RuleSet.getRule().getEnumValueName(); + continue; + } + OS << "("; + for (const auto &Rule : llvm::enumerate(RuleSet.getAggregateRuleSet())) { + if (Rule.index()) + OS << ", "; + OS << Rule.value().getEnumValueName(); + } + OS << ")"; } OS << ")\n"; } |