1b1c73532SDimitry Andric //===--- Attributes.cpp ---------------------------------------------------===//
2b1c73532SDimitry Andric //
3b1c73532SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b1c73532SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5b1c73532SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b1c73532SDimitry Andric //
7b1c73532SDimitry Andric //===----------------------------------------------------------------------===//
8b1c73532SDimitry Andric //
9b1c73532SDimitry Andric // This file implements the AttributeCommonInfo interface.
10b1c73532SDimitry Andric //
11b1c73532SDimitry Andric //===----------------------------------------------------------------------===//
12b1c73532SDimitry Andric
139f4dbff6SDimitry Andric #include "clang/Basic/Attributes.h"
14583e75ccSDimitry Andric #include "clang/Basic/AttrSubjectMatchRules.h"
159f4dbff6SDimitry Andric #include "clang/Basic/IdentifierTable.h"
16b1c73532SDimitry Andric #include "clang/Basic/LangOptions.h"
177fa27ce4SDimitry Andric #include "clang/Basic/ParsedAttrInfo.h"
18b1c73532SDimitry Andric #include "clang/Basic/TargetInfo.h"
19b1c73532SDimitry Andric
209f4dbff6SDimitry Andric using namespace clang;
219f4dbff6SDimitry Andric
hasAttributeImpl(AttributeCommonInfo::Syntax Syntax,StringRef Name,StringRef ScopeName,const TargetInfo & Target,const LangOptions & LangOpts)227fa27ce4SDimitry Andric static int hasAttributeImpl(AttributeCommonInfo::Syntax Syntax, StringRef Name,
237fa27ce4SDimitry Andric StringRef ScopeName, const TargetInfo &Target,
247fa27ce4SDimitry Andric const LangOptions &LangOpts) {
257fa27ce4SDimitry Andric
267fa27ce4SDimitry Andric #include "clang/Basic/AttrHasAttributeImpl.inc"
277fa27ce4SDimitry Andric
287fa27ce4SDimitry Andric return 0;
297fa27ce4SDimitry Andric }
307fa27ce4SDimitry Andric
hasAttribute(AttributeCommonInfo::Syntax Syntax,const IdentifierInfo * Scope,const IdentifierInfo * Attr,const TargetInfo & Target,const LangOptions & LangOpts)31145449b1SDimitry Andric int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax,
32145449b1SDimitry Andric const IdentifierInfo *Scope, const IdentifierInfo *Attr,
33145449b1SDimitry Andric const TargetInfo &Target, const LangOptions &LangOpts) {
349f4dbff6SDimitry Andric StringRef Name = Attr->getName();
359f4dbff6SDimitry Andric // Normalize the attribute name, __foo__ becomes foo.
36312c0ed1SDimitry Andric if (Name.size() >= 4 && Name.starts_with("__") && Name.ends_with("__"))
379f4dbff6SDimitry Andric Name = Name.substr(2, Name.size() - 4);
389f4dbff6SDimitry Andric
39676fbe81SDimitry Andric // Normalize the scope name, but only for gnu and clang attributes.
40676fbe81SDimitry Andric StringRef ScopeName = Scope ? Scope->getName() : "";
41676fbe81SDimitry Andric if (ScopeName == "__gnu__")
42676fbe81SDimitry Andric ScopeName = "gnu";
43676fbe81SDimitry Andric else if (ScopeName == "_Clang")
44676fbe81SDimitry Andric ScopeName = "clang";
45676fbe81SDimitry Andric
46344a3780SDimitry Andric // As a special case, look for the omp::sequence and omp::directive
47344a3780SDimitry Andric // attributes. We support those, but not through the typical attribute
48344a3780SDimitry Andric // machinery that goes through TableGen. We support this in all OpenMP modes
49344a3780SDimitry Andric // so long as double square brackets are enabled.
50ac9a064cSDimitry Andric //
51ac9a064cSDimitry Andric // Other OpenMP attributes (e.g. [[omp::assume]]) are handled via the
52ac9a064cSDimitry Andric // regular attribute parsing machinery.
53ac9a064cSDimitry Andric if (LangOpts.OpenMP && ScopeName == "omp" &&
54ac9a064cSDimitry Andric (Name == "directive" || Name == "sequence"))
55ac9a064cSDimitry Andric return 1;
56344a3780SDimitry Andric
577fa27ce4SDimitry Andric int res = hasAttributeImpl(Syntax, Name, ScopeName, Target, LangOpts);
587fa27ce4SDimitry Andric if (res)
597fa27ce4SDimitry Andric return res;
607fa27ce4SDimitry Andric
617fa27ce4SDimitry Andric // Check if any plugin provides this attribute.
627fa27ce4SDimitry Andric for (auto &Ptr : getAttributePluginInstances())
637fa27ce4SDimitry Andric if (Ptr->hasSpelling(Syntax, Name))
647fa27ce4SDimitry Andric return 1;
659f4dbff6SDimitry Andric
6606d4ba38SDimitry Andric return 0;
679f4dbff6SDimitry Andric }
68583e75ccSDimitry Andric
getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule)69583e75ccSDimitry Andric const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) {
70583e75ccSDimitry Andric switch (Rule) {
71583e75ccSDimitry Andric #define ATTR_MATCH_RULE(NAME, SPELLING, IsAbstract) \
72583e75ccSDimitry Andric case attr::NAME: \
73583e75ccSDimitry Andric return SPELLING;
74583e75ccSDimitry Andric #include "clang/Basic/AttrSubMatchRulesList.inc"
75583e75ccSDimitry Andric }
76583e75ccSDimitry Andric llvm_unreachable("Invalid subject match rule");
77583e75ccSDimitry Andric }
78519fc96cSDimitry Andric
79519fc96cSDimitry Andric static StringRef
normalizeAttrScopeName(const IdentifierInfo * Scope,AttributeCommonInfo::Syntax SyntaxUsed)80cfca06d7SDimitry Andric normalizeAttrScopeName(const IdentifierInfo *Scope,
81519fc96cSDimitry Andric AttributeCommonInfo::Syntax SyntaxUsed) {
82cfca06d7SDimitry Andric if (!Scope)
83cfca06d7SDimitry Andric return "";
84cfca06d7SDimitry Andric
85519fc96cSDimitry Andric // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name
86519fc96cSDimitry Andric // to be "clang".
87cfca06d7SDimitry Andric StringRef ScopeName = Scope->getName();
88519fc96cSDimitry Andric if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
89b1c73532SDimitry Andric SyntaxUsed == AttributeCommonInfo::AS_C23) {
90519fc96cSDimitry Andric if (ScopeName == "__gnu__")
91519fc96cSDimitry Andric ScopeName = "gnu";
92519fc96cSDimitry Andric else if (ScopeName == "_Clang")
93519fc96cSDimitry Andric ScopeName = "clang";
94519fc96cSDimitry Andric }
95519fc96cSDimitry Andric return ScopeName;
96519fc96cSDimitry Andric }
97519fc96cSDimitry Andric
normalizeAttrName(const IdentifierInfo * Name,StringRef NormalizedScopeName,AttributeCommonInfo::Syntax SyntaxUsed)98cfca06d7SDimitry Andric static StringRef normalizeAttrName(const IdentifierInfo *Name,
99519fc96cSDimitry Andric StringRef NormalizedScopeName,
100519fc96cSDimitry Andric AttributeCommonInfo::Syntax SyntaxUsed) {
101519fc96cSDimitry Andric // Normalize the attribute name, __foo__ becomes foo. This is only allowable
102519fc96cSDimitry Andric // for GNU attributes, and attributes using the double square bracket syntax.
103519fc96cSDimitry Andric bool ShouldNormalize =
104519fc96cSDimitry Andric SyntaxUsed == AttributeCommonInfo::AS_GNU ||
105519fc96cSDimitry Andric ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
106b1c73532SDimitry Andric SyntaxUsed == AttributeCommonInfo::AS_C23) &&
107519fc96cSDimitry Andric (NormalizedScopeName.empty() || NormalizedScopeName == "gnu" ||
108519fc96cSDimitry Andric NormalizedScopeName == "clang"));
109cfca06d7SDimitry Andric StringRef AttrName = Name->getName();
110312c0ed1SDimitry Andric if (ShouldNormalize && AttrName.size() >= 4 && AttrName.starts_with("__") &&
111312c0ed1SDimitry Andric AttrName.ends_with("__"))
112519fc96cSDimitry Andric AttrName = AttrName.slice(2, AttrName.size() - 2);
113519fc96cSDimitry Andric
114519fc96cSDimitry Andric return AttrName;
115519fc96cSDimitry Andric }
116519fc96cSDimitry Andric
isGNUScope() const117519fc96cSDimitry Andric bool AttributeCommonInfo::isGNUScope() const {
118519fc96cSDimitry Andric return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
119519fc96cSDimitry Andric }
120519fc96cSDimitry Andric
isClangScope() const121145449b1SDimitry Andric bool AttributeCommonInfo::isClangScope() const {
122145449b1SDimitry Andric return ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang"));
123145449b1SDimitry Andric }
124145449b1SDimitry Andric
125519fc96cSDimitry Andric #include "clang/Sema/AttrParsedAttrKinds.inc"
126519fc96cSDimitry Andric
normalizeName(const IdentifierInfo * Name,const IdentifierInfo * Scope,AttributeCommonInfo::Syntax SyntaxUsed)127cfca06d7SDimitry Andric static SmallString<64> normalizeName(const IdentifierInfo *Name,
128cfca06d7SDimitry Andric const IdentifierInfo *Scope,
129cfca06d7SDimitry Andric AttributeCommonInfo::Syntax SyntaxUsed) {
130cfca06d7SDimitry Andric StringRef ScopeName = normalizeAttrScopeName(Scope, SyntaxUsed);
131cfca06d7SDimitry Andric StringRef AttrName = normalizeAttrName(Name, ScopeName, SyntaxUsed);
132cfca06d7SDimitry Andric
133cfca06d7SDimitry Andric SmallString<64> FullName = ScopeName;
134cfca06d7SDimitry Andric if (!ScopeName.empty()) {
135cfca06d7SDimitry Andric assert(SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
136b1c73532SDimitry Andric SyntaxUsed == AttributeCommonInfo::AS_C23);
137cfca06d7SDimitry Andric FullName += "::";
138cfca06d7SDimitry Andric }
139cfca06d7SDimitry Andric FullName += AttrName;
140cfca06d7SDimitry Andric
141cfca06d7SDimitry Andric return FullName;
142cfca06d7SDimitry Andric }
143cfca06d7SDimitry Andric
144519fc96cSDimitry Andric AttributeCommonInfo::Kind
getParsedKind(const IdentifierInfo * Name,const IdentifierInfo * ScopeName,Syntax SyntaxUsed)145519fc96cSDimitry Andric AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name,
146519fc96cSDimitry Andric const IdentifierInfo *ScopeName,
147519fc96cSDimitry Andric Syntax SyntaxUsed) {
148cfca06d7SDimitry Andric return ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed);
149cfca06d7SDimitry Andric }
150519fc96cSDimitry Andric
getNormalizedFullName() const151cfca06d7SDimitry Andric std::string AttributeCommonInfo::getNormalizedFullName() const {
152cfca06d7SDimitry Andric return static_cast<std::string>(
153cfca06d7SDimitry Andric normalizeName(getAttrName(), getScopeName(), getSyntax()));
154519fc96cSDimitry Andric }
155519fc96cSDimitry Andric
calculateAttributeSpellingListIndex() const156519fc96cSDimitry Andric unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
157519fc96cSDimitry Andric // Both variables will be used in tablegen generated
158519fc96cSDimitry Andric // attribute spell list index matching code.
159519fc96cSDimitry Andric auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax());
160cfca06d7SDimitry Andric StringRef Scope = normalizeAttrScopeName(getScopeName(), Syntax);
161cfca06d7SDimitry Andric StringRef Name = normalizeAttrName(getAttrName(), Scope, Syntax);
162519fc96cSDimitry Andric
163519fc96cSDimitry Andric #include "clang/Sema/AttrSpellingListIndex.inc"
164519fc96cSDimitry Andric }
165