Author: arphaman Date: Wed Apr 19 10:52:11 2017 New Revision: 300712 URL: http://llvm.org/viewvc/llvm-project?rev=300712&view=rev Log: 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 Modified: cfe/trunk/include/clang/Basic/Attr.td cfe/trunk/lib/Sema/SemaDeclAttr.cpp cfe/trunk/test/Misc/pragma-attribute-supported-attributes-list.test cfe/trunk/test/Sema/alloc-align-attr.c cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Modified: cfe/trunk/include/clang/Basic/Attr.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=300712&r1=300711&r2=300712&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/Attr.td (original) +++ cfe/trunk/include/clang/Basic/Attr.td Wed Apr 19 10:52:11 2017 @@ -368,6 +368,16 @@ def SubjectMatcherForBlock : AttrSubject let LangOpts = [BlocksSupported]; } +// Aggregate attribute subject match rules are abstract match rules that can't +// be used directly in #pragma clang attribute. Instead, users have to use +// subject match rules that correspond to attribute subjects that derive from +// the specified subject. +class AttrSubjectMatcherAggregateRule<AttrSubject subject> { + AttrSubject Subject = subject; +} + +def SubjectMatcherForNamed : AttrSubjectMatcherAggregateRule<Named>; + class Attr { // The various ways in which an attribute can be spelled in source list<Spelling> Spellings; @@ -656,7 +666,7 @@ def ExternalSourceSymbol : InheritableAt StringArgument<"definedIn", 1>, BoolArgument<"generatedDeclaration", 1>]; let HasCustomParsing = 1; -// let Subjects = SubjectList<[Named]>; + let Subjects = SubjectList<[Named]>; let Documentation = [ExternalSourceSymbolDocs]; } Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=300712&r1=300711&r2=300712&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Wed Apr 19 10:52:11 2017 @@ -2511,12 +2511,6 @@ static void handleExternalSourceSymbolAt assert(checkAttributeAtMostNumArgs(S, Attr, 3) && "Invalid number of arguments in an external_source_symbol attribute"); - if (!isa<NamedDecl>(D)) { - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << ExpectedNamedDecl; - return; - } - StringRef Language; if (const auto *SE = dyn_cast_or_null<StringLiteral>(Attr.getArgAsExpr(0))) Language = SE->getString(); @@ -5765,18 +5759,21 @@ static void handleOpenCLNoSVMAttr(Sema & static bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D, const AttributeList &Attr) { // Several attributes carry different semantics than the parsing requires, so - // those are opted out of the common handling. + // those are opted out of the common argument checks. // // We also bail on unknown and ignored attributes because those are handled // as part of the target-specific handling logic. - if (Attr.hasCustomParsing() || - Attr.getKind() == AttributeList::UnknownAttribute) + if (Attr.getKind() == AttributeList::UnknownAttribute) return false; - // Check whether the attribute requires specific language extensions to be // enabled. if (!Attr.diagnoseLangOpts(S)) return true; + // Check whether the attribute appertains to the given subject. + if (!Attr.diagnoseAppertainsTo(S, D)) + return true; + if (Attr.hasCustomParsing()) + return false; if (Attr.getMinArgs() == Attr.getMaxArgs()) { // If there are no optional arguments, then checking for the argument count @@ -5793,10 +5790,6 @@ static bool handleCommonAttributeFeature return true; } - // Check whether the attribute appertains to the given subject. - if (!Attr.diagnoseAppertainsTo(S, D)) - return true; - return false; } Modified: cfe/trunk/test/Misc/pragma-attribute-supported-attributes-list.test URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/pragma-attribute-supported-attributes-list.test?rev=300712&r1=300711&r2=300712&view=diff ============================================================================== --- cfe/trunk/test/Misc/pragma-attribute-supported-attributes-list.test (original) +++ cfe/trunk/test/Misc/pragma-attribute-supported-attributes-list.test Wed Apr 19 10:52:11 2017 @@ -2,7 +2,7 @@ // The number of supported attributes should never go down! -// CHECK: #pragma clang attribute supports 57 attributes: +// CHECK: #pragma clang attribute supports 58 attributes: // CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function) @@ -23,6 +23,7 @@ // CHECK-NEXT: DisableTailCalls (SubjectMatchRule_function, SubjectMatchRule_objc_method) // CHECK-NEXT: EnableIf (SubjectMatchRule_function) // CHECK-NEXT: EnumExtensibility (SubjectMatchRule_enum) +// CHECK-NEXT: ExternalSourceSymbol ((SubjectMatchRule_record, SubjectMatchRule_enum, SubjectMatchRule_enum_constant, SubjectMatchRule_field, SubjectMatchRule_function, SubjectMatchRule_namespace, SubjectMatchRule_objc_category, SubjectMatchRule_objc_interface, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_objc_protocol, SubjectMatchRule_record, SubjectMatchRule_type_alias, SubjectMatchRule_variable)) // CHECK-NEXT: FlagEnum (SubjectMatchRule_enum) // CHECK-NEXT: Flatten (SubjectMatchRule_function) // CHECK-NEXT: IFunc (SubjectMatchRule_function) Modified: cfe/trunk/test/Sema/alloc-align-attr.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/alloc-align-attr.c?rev=300712&r1=300711&r2=300712&view=diff ============================================================================== --- cfe/trunk/test/Sema/alloc-align-attr.c (original) +++ cfe/trunk/test/Sema/alloc-align-attr.c Wed Apr 19 10:52:11 2017 @@ -13,7 +13,7 @@ void *test_incorrect_param_type(float a) void *test_bad_param_type(void) __attribute((alloc_align(1.1))); // expected-error {{'alloc_align' attribute requires parameter 1 to be an integer constant}} // argument count -void *test_no_fn_proto() __attribute__((alloc_align)); // expected-error {{'alloc_align' attribute takes one argument}} -void *test_no_fn_proto() __attribute__((alloc_align())); // expected-error {{'alloc_align' attribute takes one argument}} -void *test_no_fn_proto() __attribute__((alloc_align(32, 45, 37))); // expected-error {{'alloc_align' attribute takes one argument}} +void *test_no_fn_proto(int x, int y) __attribute__((alloc_align)); // expected-error {{'alloc_align' attribute takes one argument}} +void *test_no_fn_proto(int x, int y) __attribute__((alloc_align())); // expected-error {{'alloc_align' attribute takes one argument}} +void *test_no_fn_proto(int x, int y) __attribute__((alloc_align(32, 45, 37))); // expected-error {{'alloc_align' attribute takes one argument}} Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=300712&r1=300711&r2=300712&view=diff ============================================================================== --- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original) +++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Wed Apr 19 10:52:11 2017 @@ -1611,7 +1611,36 @@ const char *AttributeSubjectMatchRule::E 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::PragmaClang 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::PragmaClang 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::generateStr 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(c 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(c .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(c case ObjCProtocol | ObjCInterface: return "ExpectedObjectiveCInterfaceOrProtocol"; case Field | Var: return "ExpectedFieldOrGlobalVar"; + + case Named: + return "ExpectedNamedDecl"; } PrintFatalError(S.getLoc(), @@ -3754,9 +3833,19 @@ void EmitTestPragmaAttributeSupportedAtt 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"; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits