Attributes.cpp 4.8 KB

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