Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/Basic/Attributes.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- Attributes.cpp ---------------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file implements the AttributeCommonInfo interface.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "clang/Basic/Attributes.h"
14
#include "clang/Basic/AttrSubjectMatchRules.h"
15
#include "clang/Basic/IdentifierTable.h"
16
#include "clang/Basic/LangOptions.h"
17
#include "clang/Basic/ParsedAttrInfo.h"
18
#include "clang/Basic/TargetInfo.h"
19
20
using namespace clang;
21
22
static int hasAttributeImpl(AttributeCommonInfo::Syntax Syntax, StringRef Name,
23
                            StringRef ScopeName, const TargetInfo &Target,
24
0
                            const LangOptions &LangOpts) {
25
26
0
#include "clang/Basic/AttrHasAttributeImpl.inc"
27
28
0
  return 0;
29
0
}
30
31
int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax,
32
                        const IdentifierInfo *Scope, const IdentifierInfo *Attr,
33
0
                        const TargetInfo &Target, const LangOptions &LangOpts) {
34
0
  StringRef Name = Attr->getName();
35
  // Normalize the attribute name, __foo__ becomes foo.
36
0
  if (Name.size() >= 4 && Name.starts_with("__") && Name.ends_with("__"))
37
0
    Name = Name.substr(2, Name.size() - 4);
38
39
  // Normalize the scope name, but only for gnu and clang attributes.
40
0
  StringRef ScopeName = Scope ? Scope->getName() : "";
41
0
  if (ScopeName == "__gnu__")
42
0
    ScopeName = "gnu";
43
0
  else if (ScopeName == "_Clang")
44
0
    ScopeName = "clang";
45
46
  // As a special case, look for the omp::sequence and omp::directive
47
  // attributes. We support those, but not through the typical attribute
48
  // machinery that goes through TableGen. We support this in all OpenMP modes
49
  // so long as double square brackets are enabled.
50
0
  if (LangOpts.OpenMP && ScopeName == "omp")
51
0
    return (Name == "directive" || Name == "sequence") ? 1 : 0;
52
53
0
  int res = hasAttributeImpl(Syntax, Name, ScopeName, Target, LangOpts);
54
0
  if (res)
55
0
    return res;
56
57
  // Check if any plugin provides this attribute.
58
0
  for (auto &Ptr : getAttributePluginInstances())
59
0
    if (Ptr->hasSpelling(Syntax, Name))
60
0
      return 1;
61
62
0
  return 0;
63
0
}
64
65
0
const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) {
66
0
  switch (Rule) {
67
0
#define ATTR_MATCH_RULE(NAME, SPELLING, IsAbstract)                            \
68
0
  case attr::NAME:                                                             \
69
0
    return SPELLING;
70
0
#include "clang/Basic/AttrSubMatchRulesList.inc"
71
0
  }
72
0
  llvm_unreachable("Invalid subject match rule");
73
0
}
74
75
static StringRef
76
normalizeAttrScopeName(const IdentifierInfo *Scope,
77
0
                       AttributeCommonInfo::Syntax SyntaxUsed) {
78
0
  if (!Scope)
79
0
    return "";
80
81
  // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name
82
  // to be "clang".
83
0
  StringRef ScopeName = Scope->getName();
84
0
  if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
85
0
      SyntaxUsed == AttributeCommonInfo::AS_C23) {
86
0
    if (ScopeName == "__gnu__")
87
0
      ScopeName = "gnu";
88
0
    else if (ScopeName == "_Clang")
89
0
      ScopeName = "clang";
90
0
  }
91
0
  return ScopeName;
92
0
}
93
94
static StringRef normalizeAttrName(const IdentifierInfo *Name,
95
                                   StringRef NormalizedScopeName,
96
0
                                   AttributeCommonInfo::Syntax SyntaxUsed) {
97
  // Normalize the attribute name, __foo__ becomes foo. This is only allowable
98
  // for GNU attributes, and attributes using the double square bracket syntax.
99
0
  bool ShouldNormalize =
100
0
      SyntaxUsed == AttributeCommonInfo::AS_GNU ||
101
0
      ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
102
0
        SyntaxUsed == AttributeCommonInfo::AS_C23) &&
103
0
       (NormalizedScopeName.empty() || NormalizedScopeName == "gnu" ||
104
0
        NormalizedScopeName == "clang"));
105
0
  StringRef AttrName = Name->getName();
106
0
  if (ShouldNormalize && AttrName.size() >= 4 && AttrName.starts_with("__") &&
107
0
      AttrName.ends_with("__"))
108
0
    AttrName = AttrName.slice(2, AttrName.size() - 2);
109
110
0
  return AttrName;
111
0
}
112
113
0
bool AttributeCommonInfo::isGNUScope() const {
114
0
  return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
115
0
}
116
117
0
bool AttributeCommonInfo::isClangScope() const {
118
0
  return ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang"));
119
0
}
120
121
#include "clang/Sema/AttrParsedAttrKinds.inc"
122
123
static SmallString<64> normalizeName(const IdentifierInfo *Name,
124
                                     const IdentifierInfo *Scope,
125
0
                                     AttributeCommonInfo::Syntax SyntaxUsed) {
126
0
  StringRef ScopeName = normalizeAttrScopeName(Scope, SyntaxUsed);
127
0
  StringRef AttrName = normalizeAttrName(Name, ScopeName, SyntaxUsed);
128
129
0
  SmallString<64> FullName = ScopeName;
130
0
  if (!ScopeName.empty()) {
131
0
    assert(SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
132
0
           SyntaxUsed == AttributeCommonInfo::AS_C23);
133
0
    FullName += "::";
134
0
  }
135
0
  FullName += AttrName;
136
137
0
  return FullName;
138
0
}
139
140
AttributeCommonInfo::Kind
141
AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name,
142
                                   const IdentifierInfo *ScopeName,
143
0
                                   Syntax SyntaxUsed) {
144
0
  return ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed);
145
0
}
146
147
0
std::string AttributeCommonInfo::getNormalizedFullName() const {
148
0
  return static_cast<std::string>(
149
0
      normalizeName(getAttrName(), getScopeName(), getSyntax()));
150
0
}
151
152
0
unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
153
  // Both variables will be used in tablegen generated
154
  // attribute spell list index matching code.
155
0
  auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax());
156
0
  StringRef Scope = normalizeAttrScopeName(getScopeName(), Syntax);
157
0
  StringRef Name = normalizeAttrName(getAttrName(), Scope, Syntax);
158
159
0
#include "clang/Sema/AttrSpellingListIndex.inc"
160
0
}