1 //===--- AttrImpl.cpp - Classes for representing 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 contains out-of-line methods for Attr classes.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "clang/AST/ASTContext.h"
14 #include "clang/AST/Attr.h"
15 #include "clang/AST/Expr.h"
16 #include "clang/AST/Type.h"
17 using namespace clang;
18
printPrettyPragma(raw_ostream & OS,const PrintingPolicy & Policy) const19 void LoopHintAttr::printPrettyPragma(raw_ostream &OS,
20 const PrintingPolicy &Policy) const {
21 unsigned SpellingIndex = getAttributeSpellingListIndex();
22 // For "#pragma unroll" and "#pragma nounroll" the string "unroll" or
23 // "nounroll" is already emitted as the pragma name.
24 if (SpellingIndex == Pragma_nounroll ||
25 SpellingIndex == Pragma_nounroll_and_jam)
26 return;
27 else if (SpellingIndex == Pragma_unroll ||
28 SpellingIndex == Pragma_unroll_and_jam) {
29 OS << ' ' << getValueString(Policy);
30 return;
31 }
32
33 assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
34 OS << ' ' << getOptionName(option) << getValueString(Policy);
35 }
36
37 // Return a string containing the loop hint argument including the
38 // enclosing parentheses.
getValueString(const PrintingPolicy & Policy) const39 std::string LoopHintAttr::getValueString(const PrintingPolicy &Policy) const {
40 std::string ValueName;
41 llvm::raw_string_ostream OS(ValueName);
42 OS << "(";
43 if (state == Numeric)
44 value->printPretty(OS, nullptr, Policy);
45 else if (state == FixedWidth || state == ScalableWidth) {
46 if (value) {
47 value->printPretty(OS, nullptr, Policy);
48 if (state == ScalableWidth)
49 OS << ", scalable";
50 } else if (state == ScalableWidth)
51 OS << "scalable";
52 else
53 OS << "fixed";
54 } else if (state == Enable)
55 OS << "enable";
56 else if (state == Full)
57 OS << "full";
58 else if (state == AssumeSafety)
59 OS << "assume_safety";
60 else
61 OS << "disable";
62 OS << ")";
63 return OS.str();
64 }
65
66 // Return a string suitable for identifying this attribute in diagnostics.
67 std::string
getDiagnosticName(const PrintingPolicy & Policy) const68 LoopHintAttr::getDiagnosticName(const PrintingPolicy &Policy) const {
69 unsigned SpellingIndex = getAttributeSpellingListIndex();
70 if (SpellingIndex == Pragma_nounroll)
71 return "#pragma nounroll";
72 else if (SpellingIndex == Pragma_unroll)
73 return "#pragma unroll" +
74 (option == UnrollCount ? getValueString(Policy) : "");
75 else if (SpellingIndex == Pragma_nounroll_and_jam)
76 return "#pragma nounroll_and_jam";
77 else if (SpellingIndex == Pragma_unroll_and_jam)
78 return "#pragma unroll_and_jam" +
79 (option == UnrollAndJamCount ? getValueString(Policy) : "");
80
81 assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
82 return getOptionName(option) + getValueString(Policy);
83 }
84
printPrettyPragma(raw_ostream & OS,const PrintingPolicy & Policy) const85 void OMPDeclareSimdDeclAttr::printPrettyPragma(
86 raw_ostream &OS, const PrintingPolicy &Policy) const {
87 if (getBranchState() != BS_Undefined)
88 OS << ' ' << ConvertBranchStateTyToStr(getBranchState());
89 if (auto *E = getSimdlen()) {
90 OS << " simdlen(";
91 E->printPretty(OS, nullptr, Policy);
92 OS << ")";
93 }
94 if (uniforms_size() > 0) {
95 OS << " uniform";
96 StringRef Sep = "(";
97 for (auto *E : uniforms()) {
98 OS << Sep;
99 E->printPretty(OS, nullptr, Policy);
100 Sep = ", ";
101 }
102 OS << ")";
103 }
104 alignments_iterator NI = alignments_begin();
105 for (auto *E : aligneds()) {
106 OS << " aligned(";
107 E->printPretty(OS, nullptr, Policy);
108 if (*NI) {
109 OS << ": ";
110 (*NI)->printPretty(OS, nullptr, Policy);
111 }
112 OS << ")";
113 ++NI;
114 }
115 steps_iterator I = steps_begin();
116 modifiers_iterator MI = modifiers_begin();
117 for (auto *E : linears()) {
118 OS << " linear(";
119 if (*MI != OMPC_LINEAR_unknown)
120 OS << getOpenMPSimpleClauseTypeName(llvm::omp::Clause::OMPC_linear, *MI)
121 << "(";
122 E->printPretty(OS, nullptr, Policy);
123 if (*MI != OMPC_LINEAR_unknown)
124 OS << ")";
125 if (*I) {
126 OS << ": ";
127 (*I)->printPretty(OS, nullptr, Policy);
128 }
129 OS << ")";
130 ++I;
131 ++MI;
132 }
133 }
134
printPrettyPragma(raw_ostream & OS,const PrintingPolicy & Policy) const135 void OMPDeclareTargetDeclAttr::printPrettyPragma(
136 raw_ostream &OS, const PrintingPolicy &Policy) const {
137 // Use fake syntax because it is for testing and debugging purpose only.
138 if (getDevType() != DT_Any)
139 OS << " device_type(" << ConvertDevTypeTyToStr(getDevType()) << ")";
140 if (getMapType() != MT_To)
141 OS << ' ' << ConvertMapTypeTyToStr(getMapType());
142 }
143
144 llvm::Optional<OMPDeclareTargetDeclAttr *>
getActiveAttr(const ValueDecl * VD)145 OMPDeclareTargetDeclAttr::getActiveAttr(const ValueDecl *VD) {
146 if (!VD->hasAttrs())
147 return llvm::None;
148 unsigned Level = 0;
149 OMPDeclareTargetDeclAttr *FoundAttr = nullptr;
150 for (auto *Attr : VD->specific_attrs<OMPDeclareTargetDeclAttr>()) {
151 if (Level <= Attr->getLevel()) {
152 Level = Attr->getLevel();
153 FoundAttr = Attr;
154 }
155 }
156 if (FoundAttr)
157 return FoundAttr;
158 return llvm::None;
159 }
160
161 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
isDeclareTargetDeclaration(const ValueDecl * VD)162 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(const ValueDecl *VD) {
163 llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD);
164 if (ActiveAttr.hasValue())
165 return ActiveAttr.getValue()->getMapType();
166 return llvm::None;
167 }
168
169 llvm::Optional<OMPDeclareTargetDeclAttr::DevTypeTy>
getDeviceType(const ValueDecl * VD)170 OMPDeclareTargetDeclAttr::getDeviceType(const ValueDecl *VD) {
171 llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD);
172 if (ActiveAttr.hasValue())
173 return ActiveAttr.getValue()->getDevType();
174 return llvm::None;
175 }
176
177 llvm::Optional<SourceLocation>
getLocation(const ValueDecl * VD)178 OMPDeclareTargetDeclAttr::getLocation(const ValueDecl *VD) {
179 llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD);
180 if (ActiveAttr.hasValue())
181 return ActiveAttr.getValue()->getRange().getBegin();
182 return llvm::None;
183 }
184
185 namespace clang {
186 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const OMPTraitInfo &TI);
187 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const OMPTraitInfo *TI);
188 }
189
printPrettyPragma(raw_ostream & OS,const PrintingPolicy & Policy) const190 void OMPDeclareVariantAttr::printPrettyPragma(
191 raw_ostream &OS, const PrintingPolicy &Policy) const {
192 if (const Expr *E = getVariantFuncRef()) {
193 OS << "(";
194 E->printPretty(OS, nullptr, Policy);
195 OS << ")";
196 }
197 OS << " match(" << traitInfos << ")";
198 }
199
200 #include "clang/AST/AttrImpl.inc"
201