Attributes.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #include "clang/Basic/Attributes.h"
  2. #include "clang/Basic/AttrSubjectMatchRules.h"
  3. #include "clang/Basic/AttributeCommonInfo.h"
  4. #include "clang/Basic/IdentifierTable.h"
  5. using namespace clang;
  6. int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax,
  7. const IdentifierInfo *Scope, const IdentifierInfo *Attr,
  8. const TargetInfo &Target, const LangOptions &LangOpts) {
  9. StringRef Name = Attr->getName();
  10. // Normalize the attribute name, __foo__ becomes foo.
  11. if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
  12. Name = Name.substr(2, Name.size() - 4);
  13. // Normalize the scope name, but only for gnu and clang attributes.
  14. StringRef ScopeName = Scope ? Scope->getName() : "";
  15. if (ScopeName == "__gnu__")
  16. ScopeName = "gnu";
  17. else if (ScopeName == "_Clang")
  18. ScopeName = "clang";
  19. // As a special case, look for the omp::sequence and omp::directive
  20. // attributes. We support those, but not through the typical attribute
  21. // machinery that goes through TableGen. We support this in all OpenMP modes
  22. // so long as double square brackets are enabled.
  23. if (LangOpts.OpenMP && LangOpts.DoubleSquareBracketAttributes &&
  24. ScopeName == "omp")
  25. return (Name == "directive" || Name == "sequence") ? 1 : 0;
  26. #include "clang/Basic/AttrHasAttributeImpl.inc"
  27. return 0;
  28. }
  29. const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) {
  30. switch (Rule) {
  31. #define ATTR_MATCH_RULE(NAME, SPELLING, IsAbstract) \
  32. case attr::NAME: \
  33. return SPELLING;
  34. #include "clang/Basic/AttrSubMatchRulesList.inc"
  35. }
  36. llvm_unreachable("Invalid subject match rule");
  37. }
  38. static StringRef
  39. normalizeAttrScopeName(const IdentifierInfo *Scope,
  40. AttributeCommonInfo::Syntax SyntaxUsed) {
  41. if (!Scope)
  42. return "";
  43. // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name
  44. // to be "clang".
  45. StringRef ScopeName = Scope->getName();
  46. if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
  47. SyntaxUsed == AttributeCommonInfo::AS_C2x) {
  48. if (ScopeName == "__gnu__")
  49. ScopeName = "gnu";
  50. else if (ScopeName == "_Clang")
  51. ScopeName = "clang";
  52. }
  53. return ScopeName;
  54. }
  55. static StringRef normalizeAttrName(const IdentifierInfo *Name,
  56. StringRef NormalizedScopeName,
  57. AttributeCommonInfo::Syntax SyntaxUsed) {
  58. // Normalize the attribute name, __foo__ becomes foo. This is only allowable
  59. // for GNU attributes, and attributes using the double square bracket syntax.
  60. bool ShouldNormalize =
  61. SyntaxUsed == AttributeCommonInfo::AS_GNU ||
  62. ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
  63. SyntaxUsed == AttributeCommonInfo::AS_C2x) &&
  64. (NormalizedScopeName.empty() || NormalizedScopeName == "gnu" ||
  65. NormalizedScopeName == "clang"));
  66. StringRef AttrName = Name->getName();
  67. if (ShouldNormalize && AttrName.size() >= 4 && AttrName.startswith("__") &&
  68. AttrName.endswith("__"))
  69. AttrName = AttrName.slice(2, AttrName.size() - 2);
  70. return AttrName;
  71. }
  72. bool AttributeCommonInfo::isGNUScope() const {
  73. return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
  74. }
  75. bool AttributeCommonInfo::isClangScope() const {
  76. return ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang"));
  77. }
  78. #include "clang/Sema/AttrParsedAttrKinds.inc"
  79. static SmallString<64> normalizeName(const IdentifierInfo *Name,
  80. const IdentifierInfo *Scope,
  81. AttributeCommonInfo::Syntax SyntaxUsed) {
  82. StringRef ScopeName = normalizeAttrScopeName(Scope, SyntaxUsed);
  83. StringRef AttrName = normalizeAttrName(Name, ScopeName, SyntaxUsed);
  84. SmallString<64> FullName = ScopeName;
  85. if (!ScopeName.empty()) {
  86. assert(SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
  87. SyntaxUsed == AttributeCommonInfo::AS_C2x);
  88. FullName += "::";
  89. }
  90. FullName += AttrName;
  91. return FullName;
  92. }
  93. AttributeCommonInfo::Kind
  94. AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name,
  95. const IdentifierInfo *ScopeName,
  96. Syntax SyntaxUsed) {
  97. return ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed);
  98. }
  99. std::string AttributeCommonInfo::getNormalizedFullName() const {
  100. return static_cast<std::string>(
  101. normalizeName(getAttrName(), getScopeName(), getSyntax()));
  102. }
  103. unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
  104. // Both variables will be used in tablegen generated
  105. // attribute spell list index matching code.
  106. auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax());
  107. StringRef Scope = normalizeAttrScopeName(getScopeName(), Syntax);
  108. StringRef Name = normalizeAttrName(getAttrName(), Scope, Syntax);
  109. #include "clang/Sema/AttrSpellingListIndex.inc"
  110. }