1 //===--- AttrImpl.cpp - Classes for representing attributes -----*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains out-of-line methods for Attr classes.
11 //===----------------------------------------------------------------------===//
13 #include "clang/AST/ASTContext.h"
14 #include "clang/AST/Attr.h"
15 #include "clang/AST/Expr.h"
16 #include "clang/AST/Type.h"
18 using namespace clang
;
20 void LoopHintAttr::printPrettyPragma(raw_ostream
&OS
,
21 const PrintingPolicy
&Policy
) const {
22 unsigned SpellingIndex
= getAttributeSpellingListIndex();
23 // For "#pragma unroll" and "#pragma nounroll" the string "unroll" or
24 // "nounroll" is already emitted as the pragma name.
25 if (SpellingIndex
== Pragma_nounroll
||
26 SpellingIndex
== Pragma_nounroll_and_jam
)
28 else if (SpellingIndex
== Pragma_unroll
||
29 SpellingIndex
== Pragma_unroll_and_jam
) {
30 OS
<< ' ' << getValueString(Policy
);
34 assert(SpellingIndex
== Pragma_clang_loop
&& "Unexpected spelling");
35 OS
<< ' ' << getOptionName(option
) << getValueString(Policy
);
38 // Return a string containing the loop hint argument including the
39 // enclosing parentheses.
40 std::string
LoopHintAttr::getValueString(const PrintingPolicy
&Policy
) const {
41 std::string ValueName
;
42 llvm::raw_string_ostream
OS(ValueName
);
45 value
->printPretty(OS
, nullptr, Policy
);
46 else if (state
== FixedWidth
|| state
== ScalableWidth
) {
48 value
->printPretty(OS
, nullptr, Policy
);
49 if (state
== ScalableWidth
)
51 } else if (state
== ScalableWidth
)
55 } else if (state
== Enable
)
57 else if (state
== Full
)
59 else if (state
== AssumeSafety
)
60 OS
<< "assume_safety";
67 // Return a string suitable for identifying this attribute in diagnostics.
69 LoopHintAttr::getDiagnosticName(const PrintingPolicy
&Policy
) const {
70 unsigned SpellingIndex
= getAttributeSpellingListIndex();
71 if (SpellingIndex
== Pragma_nounroll
)
72 return "#pragma nounroll";
73 else if (SpellingIndex
== Pragma_unroll
)
74 return "#pragma unroll" +
75 (option
== UnrollCount
? getValueString(Policy
) : "");
76 else if (SpellingIndex
== Pragma_nounroll_and_jam
)
77 return "#pragma nounroll_and_jam";
78 else if (SpellingIndex
== Pragma_unroll_and_jam
)
79 return "#pragma unroll_and_jam" +
80 (option
== UnrollAndJamCount
? getValueString(Policy
) : "");
82 assert(SpellingIndex
== Pragma_clang_loop
&& "Unexpected spelling");
83 return getOptionName(option
) + getValueString(Policy
);
86 void OMPDeclareSimdDeclAttr::printPrettyPragma(
87 raw_ostream
&OS
, const PrintingPolicy
&Policy
) const {
88 if (getBranchState() != BS_Undefined
)
89 OS
<< ' ' << ConvertBranchStateTyToStr(getBranchState());
90 if (auto *E
= getSimdlen()) {
92 E
->printPretty(OS
, nullptr, Policy
);
95 if (uniforms_size() > 0) {
98 for (auto *E
: uniforms()) {
100 E
->printPretty(OS
, nullptr, Policy
);
105 alignments_iterator NI
= alignments_begin();
106 for (auto *E
: aligneds()) {
108 E
->printPretty(OS
, nullptr, Policy
);
111 (*NI
)->printPretty(OS
, nullptr, Policy
);
116 steps_iterator I
= steps_begin();
117 modifiers_iterator MI
= modifiers_begin();
118 for (auto *E
: linears()) {
120 if (*MI
!= OMPC_LINEAR_unknown
)
121 OS
<< getOpenMPSimpleClauseTypeName(llvm::omp::Clause::OMPC_linear
, *MI
)
123 E
->printPretty(OS
, nullptr, Policy
);
124 if (*MI
!= OMPC_LINEAR_unknown
)
128 (*I
)->printPretty(OS
, nullptr, Policy
);
136 void OMPDeclareTargetDeclAttr::printPrettyPragma(
137 raw_ostream
&OS
, const PrintingPolicy
&Policy
) const {
138 // Use fake syntax because it is for testing and debugging purpose only.
139 if (getDevType() != DT_Any
)
140 OS
<< " device_type(" << ConvertDevTypeTyToStr(getDevType()) << ")";
141 if (getMapType() != MT_To
&& getMapType() != MT_Enter
)
142 OS
<< ' ' << ConvertMapTypeTyToStr(getMapType());
143 if (Expr
*E
= getIndirectExpr()) {
145 E
->printPretty(OS
, nullptr, Policy
);
147 } else if (getIndirect()) {
152 std::optional
<OMPDeclareTargetDeclAttr
*>
153 OMPDeclareTargetDeclAttr::getActiveAttr(const ValueDecl
*VD
) {
154 if (llvm::all_of(VD
->redecls(), [](const Decl
*D
) { return !D
->hasAttrs(); }))
157 OMPDeclareTargetDeclAttr
*FoundAttr
= nullptr;
158 for (const Decl
*D
: VD
->redecls()) {
159 for (auto *Attr
: D
->specific_attrs
<OMPDeclareTargetDeclAttr
>()) {
160 if (Level
<= Attr
->getLevel()) {
161 Level
= Attr
->getLevel();
171 std::optional
<OMPDeclareTargetDeclAttr::MapTypeTy
>
172 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(const ValueDecl
*VD
) {
173 std::optional
<OMPDeclareTargetDeclAttr
*> ActiveAttr
= getActiveAttr(VD
);
175 return (*ActiveAttr
)->getMapType();
179 std::optional
<OMPDeclareTargetDeclAttr::DevTypeTy
>
180 OMPDeclareTargetDeclAttr::getDeviceType(const ValueDecl
*VD
) {
181 std::optional
<OMPDeclareTargetDeclAttr
*> ActiveAttr
= getActiveAttr(VD
);
183 return (*ActiveAttr
)->getDevType();
187 std::optional
<SourceLocation
>
188 OMPDeclareTargetDeclAttr::getLocation(const ValueDecl
*VD
) {
189 std::optional
<OMPDeclareTargetDeclAttr
*> ActiveAttr
= getActiveAttr(VD
);
191 return (*ActiveAttr
)->getRange().getBegin();
196 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, const OMPTraitInfo
&TI
);
197 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, const OMPTraitInfo
*TI
);
200 void OMPDeclareVariantAttr::printPrettyPragma(
201 raw_ostream
&OS
, const PrintingPolicy
&Policy
) const {
202 if (const Expr
*E
= getVariantFuncRef()) {
204 E
->printPretty(OS
, nullptr, Policy
);
207 OS
<< " match(" << traitInfos
<< ")";
209 auto PrintExprs
= [&OS
, &Policy
](Expr
**Begin
, Expr
**End
) {
210 for (Expr
**I
= Begin
; I
!= End
; ++I
) {
211 assert(*I
&& "Expected non-null Stmt");
214 (*I
)->printPretty(OS
, nullptr, Policy
);
217 if (adjustArgsNothing_size()) {
218 OS
<< " adjust_args(nothing:";
219 PrintExprs(adjustArgsNothing_begin(), adjustArgsNothing_end());
222 if (adjustArgsNeedDevicePtr_size()) {
223 OS
<< " adjust_args(need_device_ptr:";
224 PrintExprs(adjustArgsNeedDevicePtr_begin(), adjustArgsNeedDevicePtr_end());
228 auto PrintInteropInfo
= [&OS
](OMPInteropInfo
*Begin
, OMPInteropInfo
*End
) {
229 for (OMPInteropInfo
*I
= Begin
; I
!= End
; ++I
) {
233 OS
<< getInteropTypeString(I
);
237 if (appendArgs_size()) {
238 OS
<< " append_args(";
239 PrintInteropInfo(appendArgs_begin(), appendArgs_end());
244 unsigned AlignedAttr::getAlignment(ASTContext
&Ctx
) const {
245 assert(!isAlignmentDependent());
246 if (getCachedAlignmentValue())
247 return *getCachedAlignmentValue();
249 // Handle alignmentType case.
250 if (!isAlignmentExpr()) {
251 QualType T
= getAlignmentType()->getType();
253 // C++ [expr.alignof]p3:
254 // When alignof is applied to a reference type, the result is the
255 // alignment of the referenced type.
256 T
= T
.getNonReferenceType();
258 if (T
.getQualifiers().hasUnaligned())
259 return Ctx
.getCharWidth();
261 return Ctx
.getTypeAlignInChars(T
.getTypePtr()).getQuantity() *
265 // Handle alignmentExpr case.
267 return alignmentExpr
->EvaluateKnownConstInt(Ctx
).getZExtValue() *
270 return Ctx
.getTargetDefaultAlignForAttributeAligned();
273 #include "clang/AST/AttrImpl.inc"