1 //======- AttributeCommonInfo.h - Base info about Attributes-----*- C++ -*-===// 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 defines the AttributeCommonInfo type, which is the base for a 10 // ParsedAttr and is used by Attr as a way to share info between the two. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H 15 #define LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H 16 #include "clang/Basic/SourceLocation.h" 17 18 namespace clang { 19 class IdentifierInfo; 20 class ASTRecordWriter; 21 22 class AttributeCommonInfo { 23 public: 24 /// The style used to specify an attribute. 25 enum Syntax { 26 /// __attribute__((...)) 27 AS_GNU, 28 29 /// [[...]] 30 AS_CXX11, 31 32 /// [[...]] 33 AS_C2x, 34 35 /// __declspec(...) 36 AS_Declspec, 37 38 /// [uuid("...")] class Foo 39 AS_Microsoft, 40 41 /// __ptr16, alignas(...), etc. 42 AS_Keyword, 43 44 /// #pragma ... 45 AS_Pragma, 46 47 // Note TableGen depends on the order above. Do not add or change the order 48 // without adding related code to TableGen/ClangAttrEmitter.cpp. 49 /// Context-sensitive version of a keyword attribute. 50 AS_ContextSensitiveKeyword, 51 52 /// <vardecl> : <semantic> 53 AS_HLSLSemantic, 54 }; 55 enum Kind { 56 #define PARSED_ATTR(NAME) AT_##NAME, 57 #include "clang/Sema/AttrParsedAttrList.inc" 58 #undef PARSED_ATTR 59 NoSemaHandlerAttribute, 60 IgnoredAttribute, 61 UnknownAttribute, 62 }; 63 64 private: 65 const IdentifierInfo *AttrName = nullptr; 66 const IdentifierInfo *ScopeName = nullptr; 67 SourceRange AttrRange; 68 const SourceLocation ScopeLoc; 69 // Corresponds to the Kind enum. 70 unsigned AttrKind : 16; 71 /// Corresponds to the Syntax enum. 72 unsigned SyntaxUsed : 4; 73 unsigned SpellingIndex : 4; 74 75 protected: 76 static constexpr unsigned SpellingNotCalculated = 0xf; 77 78 public: AttributeCommonInfo(SourceRange AttrRange)79 AttributeCommonInfo(SourceRange AttrRange) 80 : AttrRange(AttrRange), ScopeLoc(), AttrKind(0), SyntaxUsed(0), 81 SpellingIndex(SpellingNotCalculated) {} 82 AttributeCommonInfo(SourceLocation AttrLoc)83 AttributeCommonInfo(SourceLocation AttrLoc) 84 : AttrRange(AttrLoc), ScopeLoc(), AttrKind(0), SyntaxUsed(0), 85 SpellingIndex(SpellingNotCalculated) {} 86 AttributeCommonInfo(const IdentifierInfo * AttrName,const IdentifierInfo * ScopeName,SourceRange AttrRange,SourceLocation ScopeLoc,Syntax SyntaxUsed)87 AttributeCommonInfo(const IdentifierInfo *AttrName, 88 const IdentifierInfo *ScopeName, SourceRange AttrRange, 89 SourceLocation ScopeLoc, Syntax SyntaxUsed) 90 : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange), 91 ScopeLoc(ScopeLoc), 92 AttrKind(getParsedKind(AttrName, ScopeName, SyntaxUsed)), 93 SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated) {} 94 AttributeCommonInfo(const IdentifierInfo * AttrName,const IdentifierInfo * ScopeName,SourceRange AttrRange,SourceLocation ScopeLoc,Kind AttrKind,Syntax SyntaxUsed)95 AttributeCommonInfo(const IdentifierInfo *AttrName, 96 const IdentifierInfo *ScopeName, SourceRange AttrRange, 97 SourceLocation ScopeLoc, Kind AttrKind, Syntax SyntaxUsed) 98 : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange), 99 ScopeLoc(ScopeLoc), AttrKind(AttrKind), SyntaxUsed(SyntaxUsed), 100 SpellingIndex(SpellingNotCalculated) {} 101 AttributeCommonInfo(const IdentifierInfo * AttrName,const IdentifierInfo * ScopeName,SourceRange AttrRange,SourceLocation ScopeLoc,Kind AttrKind,Syntax SyntaxUsed,unsigned Spelling)102 AttributeCommonInfo(const IdentifierInfo *AttrName, 103 const IdentifierInfo *ScopeName, SourceRange AttrRange, 104 SourceLocation ScopeLoc, Kind AttrKind, Syntax SyntaxUsed, 105 unsigned Spelling) 106 : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange), 107 ScopeLoc(ScopeLoc), AttrKind(AttrKind), SyntaxUsed(SyntaxUsed), 108 SpellingIndex(Spelling) {} 109 AttributeCommonInfo(const IdentifierInfo * AttrName,SourceRange AttrRange,Syntax SyntaxUsed)110 AttributeCommonInfo(const IdentifierInfo *AttrName, SourceRange AttrRange, 111 Syntax SyntaxUsed) 112 : AttrName(AttrName), ScopeName(nullptr), AttrRange(AttrRange), 113 ScopeLoc(), AttrKind(getParsedKind(AttrName, ScopeName, SyntaxUsed)), 114 SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated) {} 115 AttributeCommonInfo(SourceRange AttrRange,Kind K,Syntax SyntaxUsed)116 AttributeCommonInfo(SourceRange AttrRange, Kind K, Syntax SyntaxUsed) 117 : AttrName(nullptr), ScopeName(nullptr), AttrRange(AttrRange), ScopeLoc(), 118 AttrKind(K), SyntaxUsed(SyntaxUsed), 119 SpellingIndex(SpellingNotCalculated) {} 120 AttributeCommonInfo(SourceRange AttrRange,Kind K,Syntax SyntaxUsed,unsigned Spelling)121 AttributeCommonInfo(SourceRange AttrRange, Kind K, Syntax SyntaxUsed, 122 unsigned Spelling) 123 : AttrName(nullptr), ScopeName(nullptr), AttrRange(AttrRange), ScopeLoc(), 124 AttrKind(K), SyntaxUsed(SyntaxUsed), SpellingIndex(Spelling) {} 125 126 AttributeCommonInfo(AttributeCommonInfo &&) = default; 127 AttributeCommonInfo(const AttributeCommonInfo &) = default; 128 getParsedKind()129 Kind getParsedKind() const { return Kind(AttrKind); } getSyntax()130 Syntax getSyntax() const { return Syntax(SyntaxUsed); } getAttrName()131 const IdentifierInfo *getAttrName() const { return AttrName; } getLoc()132 SourceLocation getLoc() const { return AttrRange.getBegin(); } getRange()133 SourceRange getRange() const { return AttrRange; } setRange(SourceRange R)134 void setRange(SourceRange R) { AttrRange = R; } 135 hasScope()136 bool hasScope() const { return ScopeName; } getScopeName()137 const IdentifierInfo *getScopeName() const { return ScopeName; } getScopeLoc()138 SourceLocation getScopeLoc() const { return ScopeLoc; } 139 140 /// Gets the normalized full name, which consists of both scope and name and 141 /// with surrounding underscores removed as appropriate (e.g. 142 /// __gnu__::__attr__ will be normalized to gnu::attr). 143 std::string getNormalizedFullName() const; 144 isDeclspecAttribute()145 bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; } isMicrosoftAttribute()146 bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; } 147 148 bool isGNUScope() const; 149 bool isClangScope() const; 150 isAlignasAttribute()151 bool isAlignasAttribute() const { 152 // FIXME: Use a better mechanism to determine this. 153 // We use this in `isCXX11Attribute` below, so it _should_ only return 154 // true for the `alignas` spelling, but it currently also returns true 155 // for the `_Alignas` spelling, which only exists in C11. Distinguishing 156 // between the two is important because they behave differently: 157 // - `alignas` may only appear in the attribute-specifier-seq before 158 // the decl-specifier-seq and is therefore associated with the 159 // declaration. 160 // - `_Alignas` may appear anywhere within the declaration-specifiers 161 // and is therefore associated with the `DeclSpec`. 162 // It's not clear how best to fix this: 163 // - We have the necessary information in the form of the `SpellingIndex`, 164 // but we would need to compare against AlignedAttr::Keyword_alignas, 165 // and we can't depend on clang/AST/Attr.h here. 166 // - We could test `getAttrName()->getName() == "alignas"`, but this is 167 // inefficient. 168 return getParsedKind() == AT_Aligned && isKeywordAttribute(); 169 } 170 isCXX11Attribute()171 bool isCXX11Attribute() const { 172 return SyntaxUsed == AS_CXX11 || isAlignasAttribute(); 173 } 174 isC2xAttribute()175 bool isC2xAttribute() const { return SyntaxUsed == AS_C2x; } 176 177 /// The attribute is spelled [[]] in either C or C++ mode, including standard 178 /// attributes spelled with a keyword, like alignas. isStandardAttributeSyntax()179 bool isStandardAttributeSyntax() const { 180 return isCXX11Attribute() || isC2xAttribute(); 181 } 182 isGNUAttribute()183 bool isGNUAttribute() const { return SyntaxUsed == AS_GNU; } 184 isKeywordAttribute()185 bool isKeywordAttribute() const { 186 return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword; 187 } 188 isContextSensitiveKeywordAttribute()189 bool isContextSensitiveKeywordAttribute() const { 190 return SyntaxUsed == AS_ContextSensitiveKeyword; 191 } 192 getAttributeSpellingListIndex()193 unsigned getAttributeSpellingListIndex() const { 194 assert((isAttributeSpellingListCalculated() || AttrName) && 195 "Spelling cannot be found"); 196 return isAttributeSpellingListCalculated() 197 ? SpellingIndex 198 : calculateAttributeSpellingListIndex(); 199 } setAttributeSpellingListIndex(unsigned V)200 void setAttributeSpellingListIndex(unsigned V) { SpellingIndex = V; } 201 202 static Kind getParsedKind(const IdentifierInfo *Name, 203 const IdentifierInfo *Scope, Syntax SyntaxUsed); 204 205 private: 206 /// Get an index into the attribute spelling list 207 /// defined in Attr.td. This index is used by an attribute 208 /// to pretty print itself. 209 unsigned calculateAttributeSpellingListIndex() const; 210 211 friend class clang::ASTRecordWriter; 212 // Used exclusively by ASTDeclWriter to get the raw spelling list state. getAttributeSpellingListIndexRaw()213 unsigned getAttributeSpellingListIndexRaw() const { return SpellingIndex; } 214 215 protected: isAttributeSpellingListCalculated()216 bool isAttributeSpellingListCalculated() const { 217 return SpellingIndex != SpellingNotCalculated; 218 } 219 }; 220 } // namespace clang 221 222 #endif // LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H 223