clang 24.0.0git
AttrImpl.cpp
Go to the documentation of this file.
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
15#include "clang/AST/Attr.h"
16#include "clang/AST/Expr.h"
18#include "clang/AST/Type.h"
19#include <optional>
20#include <type_traits>
21using namespace clang;
22
23void LoopHintAttr::printPrettyPragma(raw_ostream &OS,
24 const PrintingPolicy &Policy) const {
25 unsigned SpellingIndex = getAttributeSpellingListIndex();
26 // For "#pragma unroll" and "#pragma nounroll" the string "unroll" or
27 // "nounroll" is already emitted as the pragma name.
28 if (SpellingIndex == Pragma_nounroll ||
29 SpellingIndex == Pragma_nounroll_and_jam)
30 return;
31 else if (SpellingIndex == Pragma_unroll ||
32 SpellingIndex == Pragma_unroll_and_jam) {
33 OS << ' ' << getValueString(Policy);
34 return;
35 }
36
37 assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
38 OS << ' ' << getOptionName(option) << getValueString(Policy);
39}
40
41// Return a string containing the loop hint argument including the
42// enclosing parentheses.
43std::string LoopHintAttr::getValueString(const PrintingPolicy &Policy) const {
44 std::string ValueName;
45 llvm::raw_string_ostream OS(ValueName);
46 OS << "(";
47 if (state == Numeric)
48 value->printPretty(OS, nullptr, Policy);
49 else if (state == FixedWidth || state == ScalableWidth) {
50 if (value) {
51 value->printPretty(OS, nullptr, Policy);
52 if (state == ScalableWidth)
53 OS << ", scalable";
54 } else if (state == ScalableWidth)
55 OS << "scalable";
56 else
57 OS << "fixed";
58 } else if (state == Enable)
59 OS << "enable";
60 else if (state == Full)
61 OS << "full";
62 else if (state == AssumeSafety)
63 OS << "assume_safety";
64 else
65 OS << "disable";
66 OS << ")";
67 return ValueName;
68}
69
70// Return a string suitable for identifying this attribute in diagnostics.
71std::string
72LoopHintAttr::getDiagnosticName(const PrintingPolicy &Policy) const {
73 unsigned SpellingIndex = getAttributeSpellingListIndex();
74 if (SpellingIndex == Pragma_nounroll)
75 return "#pragma nounroll";
76 else if (SpellingIndex == Pragma_unroll)
77 return "#pragma unroll" +
78 (option == UnrollCount ? getValueString(Policy) : "");
79 else if (SpellingIndex == Pragma_nounroll_and_jam)
80 return "#pragma nounroll_and_jam";
81 else if (SpellingIndex == Pragma_unroll_and_jam)
82 return "#pragma unroll_and_jam" +
83 (option == UnrollAndJamCount ? getValueString(Policy) : "");
84
85 assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
86 return getOptionName(option) + getValueString(Policy);
87}
88
89void OMPDeclareSimdDeclAttr::printPrettyPragma(
90 raw_ostream &OS, const PrintingPolicy &Policy) const {
91 if (getBranchState() != BS_Undefined)
92 OS << ' ' << ConvertBranchStateTyToStr(getBranchState());
93 if (auto *E = getSimdlen()) {
94 OS << " simdlen(";
95 E->printPretty(OS, nullptr, Policy);
96 OS << ")";
97 }
98 if (uniforms_size() > 0) {
99 OS << " uniform";
100 StringRef Sep = "(";
101 for (auto *E : uniforms()) {
102 OS << Sep;
103 E->printPretty(OS, nullptr, Policy);
104 Sep = ", ";
105 }
106 OS << ")";
107 }
108 alignments_iterator NI = alignments_begin();
109 for (auto *E : aligneds()) {
110 OS << " aligned(";
111 E->printPretty(OS, nullptr, Policy);
112 if (*NI) {
113 OS << ": ";
114 (*NI)->printPretty(OS, nullptr, Policy);
115 }
116 OS << ")";
117 ++NI;
118 }
119 steps_iterator I = steps_begin();
120 modifiers_iterator MI = modifiers_begin();
121 for (auto *E : linears()) {
122 OS << " linear(";
123 if (*MI != OMPC_LINEAR_unknown)
124 OS << getOpenMPSimpleClauseTypeName(llvm::omp::Clause::OMPC_linear, *MI)
125 << "(";
126 E->printPretty(OS, nullptr, Policy);
127 if (*MI != OMPC_LINEAR_unknown)
128 OS << ")";
129 if (*I) {
130 OS << ": ";
131 (*I)->printPretty(OS, nullptr, Policy);
132 }
133 OS << ")";
134 ++I;
135 ++MI;
136 }
137}
138
139void OMPDeclareTargetDeclAttr::printPrettyPragma(
140 raw_ostream &OS, const PrintingPolicy &Policy) const {
141 // Use fake syntax because it is for testing and debugging purpose only.
142 if (getDevType() != DT_Any)
143 OS << " device_type(" << ConvertDevTypeTyToStr(getDevType()) << ")";
144 if (getMapType() != MT_To && getMapType() != MT_Enter)
145 OS << ' ' << ConvertMapTypeTyToStr(getMapType());
146 if (Expr *E = getIndirectExpr()) {
147 OS << " indirect(";
148 E->printPretty(OS, nullptr, Policy);
149 OS << ")";
150 } else if (getIndirect()) {
151 OS << " indirect";
152 }
153}
154
155std::optional<OMPDeclareTargetDeclAttr *>
156OMPDeclareTargetDeclAttr::getActiveAttr(const ValueDecl *VD) {
157 if (llvm::all_of(VD->redecls(), [](const Decl *D) { return !D->hasAttrs(); }))
158 return std::nullopt;
159 unsigned Level = 0;
160 OMPDeclareTargetDeclAttr *FoundAttr = nullptr;
161 for (const Decl *D : VD->redecls()) {
162 for (auto *Attr : D->specific_attrs<OMPDeclareTargetDeclAttr>()) {
163 if (Level <= Attr->getLevel()) {
164 Level = Attr->getLevel();
165 FoundAttr = Attr;
166 }
167 }
168 }
169 if (FoundAttr)
170 return FoundAttr;
171 return std::nullopt;
172}
173
174std::optional<OMPDeclareTargetDeclAttr::MapTypeTy>
175OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(const ValueDecl *VD) {
176 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD);
177 if (ActiveAttr)
178 return (*ActiveAttr)->getMapType();
179 return std::nullopt;
180}
181
182std::optional<OMPDeclareTargetDeclAttr::DevTypeTy>
183OMPDeclareTargetDeclAttr::getDeviceType(const ValueDecl *VD) {
184 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD);
185 if (ActiveAttr)
186 return (*ActiveAttr)->getDevType();
187 return std::nullopt;
188}
189
190std::optional<SourceLocation>
191OMPDeclareTargetDeclAttr::getLocation(const ValueDecl *VD) {
192 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD);
193 if (ActiveAttr)
194 return (*ActiveAttr)->getRange().getBegin();
195 return std::nullopt;
196}
197
198namespace clang {
199llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const OMPTraitInfo &TI);
200llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const OMPTraitInfo *TI);
201}
202
203void OMPDeclareVariantAttr::printPrettyPragma(
204 raw_ostream &OS, const PrintingPolicy &Policy) const {
205 if (const Expr *E = getVariantFuncRef()) {
206 OS << "(";
207 E->printPretty(OS, nullptr, Policy);
208 OS << ")";
209 }
210 OS << " match(" << traitInfos << ")";
211
212 auto PrintBound = [&OS, &Policy](const OMPAdjustArgsItem::Bound &Bound) {
213 if (Bound.Kind == OMPAdjustArgsItem::Bound::Omitted)
214 return;
215 if (Bound.Kind == OMPAdjustArgsItem::Bound::NumArgs) {
216 OS << "omp_num_args";
217 if (Bound.E)
218 OS << (Bound.IsSubtraction ? "-" : "+");
219 }
220 if (Bound.E)
221 Bound.E->printPretty(OS, nullptr, Policy);
222 };
223 auto PrintItem = [&OS, &Policy, &PrintBound](const OMPAdjustArgsItem &Item) {
224 if (Item.Kind == OMPAdjustArgsItem::Single) {
225 assert(Item.E && "expected adjust_args expression");
226 Item.E->printPretty(OS, nullptr, Policy);
227 return;
228 }
229 PrintBound(Item.Lower);
230 OS << ":";
231 PrintBound(Item.Upper);
232 };
233 for (const OMPAdjustArgsDescriptor *Desc : adjustArgs()) {
234 OS << " adjust_args("
235 << getOpenMPSimpleClauseTypeName(llvm::omp::OMPC_adjust_args,
236 Desc->AdjustOp);
237 if (Desc->AdjustOp == OMPC_ADJUST_ARGS_need_device_ptr &&
238 Desc->NeedDevicePtrModifier != OMPC_NEED_DEVICE_PTR_unknown) {
239 OS << "(";
240 switch (Desc->NeedDevicePtrModifier) {
241 case OMPC_NEED_DEVICE_PTR_fb_nullify:
242 OS << "fb_nullify";
243 break;
244 case OMPC_NEED_DEVICE_PTR_fb_preserve:
245 OS << "fb_preserve";
246 break;
248 llvm_unreachable("unexpected need_device_ptr modifier");
249 }
250 OS << ")";
251 }
252 OS << ":";
253 ArrayRef<OMPAdjustArgsItem> Items = Desc->items();
254 if (!Items.empty() && Items.front().Kind == OMPAdjustArgsItem::Range &&
255 Items.front().Lower.Kind == OMPAdjustArgsItem::Bound::Omitted)
256 OS << " ";
257 llvm::interleave(Items, PrintItem, [&OS] { OS << ","; });
258 OS << ")";
259 }
260
261 auto PrintInteropInfo = [&OS, &Policy](OMPInteropInfo *Begin,
262 OMPInteropInfo *End) {
263 for (OMPInteropInfo *I = Begin; I != End; ++I) {
264 if (I != Begin)
265 OS << ", ";
266 OS << "interop(";
267 if (!I->Prefs.empty()) {
268 OS << "prefer_type(";
269 if (I->HasPreferAttrs) {
270 StringRef Sep = "";
271 for (const auto &P : I->Prefs) {
272 OS << Sep << "{";
273 if (P.Fr) {
274 OS << "fr(";
275 P.Fr->printPretty(OS, nullptr, Policy);
276 OS << ")";
277 }
278 bool NeedSep = P.Fr != nullptr;
279 for (Expr *A : P.Attrs) {
280 if (NeedSep)
281 OS << ",";
282 OS << "attr(";
283 A->printPretty(OS, nullptr, Policy);
284 OS << ")";
285 NeedSep = true;
286 }
287 OS << "}";
288 Sep = ",";
289 }
290 } else {
291 StringRef Sep = "";
292 for (const auto &P : I->Prefs) {
293 OS << Sep;
294 if (P.Fr)
295 P.Fr->printPretty(OS, nullptr, Policy);
296 Sep = ",";
297 }
298 }
299 OS << "),";
300 }
301 OS << getInteropTypeString(I);
302 OS << ")";
303 }
304 };
305 if (appendArgs_size()) {
306 OS << " append_args(";
307 PrintInteropInfo(appendArgs_begin(), appendArgs_end());
308 OS << ")";
309 }
310}
311
312unsigned AlignedAttr::getAlignment(ASTContext &Ctx) const {
313 assert(!isAlignmentDependent());
314 if (getCachedAlignmentValue())
315 return *getCachedAlignmentValue();
316
317 // Handle alignmentType case.
318 if (!isAlignmentExpr()) {
319 QualType T = getAlignmentType()->getType();
320
321 // C++ [expr.alignof]p3:
322 // When alignof is applied to a reference type, the result is the
323 // alignment of the referenced type.
324 T = T.getNonReferenceType();
325
326 if (T.getQualifiers().hasUnaligned())
327 return Ctx.getCharWidth();
328
329 return Ctx.getTypeAlignInChars(T.getTypePtr()).getQuantity() *
330 Ctx.getCharWidth();
331 }
332
333 // Handle alignmentExpr case.
334 if (alignmentExpr)
335 return alignmentExpr->EvaluateKnownConstInt(Ctx).getZExtValue() *
336 Ctx.getCharWidth();
337
339}
340
341StringLiteral *FormatMatchesAttr::getFormatString() const {
342 return cast<StringLiteral>(getExpectedFormat());
343}
344
345namespace {
346// Arguments whose types fail this test never compare equal unless there's a
347// specialization of equalAttrArgs for the type. Specilization for the following
348// arguments haven't been implemented yet:
349// - DeclArgument
350// - OMPTraitInfoArgument
351// - VariadicOMPInteropInfoArgument
352#define USE_DEFAULT_EQUALITY \
353 (std::is_same_v<T, StringRef> || std::is_same_v<T, VersionTuple> || \
354 std::is_same_v<T, IdentifierInfo *> || std::is_same_v<T, char *> || \
355 std::is_enum_v<T> || std::is_integral_v<T>)
356
357template <class T>
358typename std::enable_if_t<!USE_DEFAULT_EQUALITY, bool>
359equalAttrArgs(T A, T B, StructuralEquivalenceContext &Context) {
360 return false;
361}
362
363template <class T>
364typename std::enable_if_t<USE_DEFAULT_EQUALITY, bool>
365equalAttrArgs(T A1, T A2, StructuralEquivalenceContext &Context) {
366 return A1 == A2;
367}
368
369template <>
370bool equalAttrArgs<ParamIdx>(ParamIdx P1, ParamIdx P2,
372 // ParamIdx can be invalid when representing an optional parameter that was
373 // not specified (e.g. the second argument of alloc_size(N)).
374 // ParamIdx::operator== asserts both sides are valid, so guard against the
375 // invalid case before delegating to it.
376 if (P1.isValid() != P2.isValid())
377 return false;
378 if (!P1.isValid())
379 return true;
380 return P1 == P2;
381}
382
383template <class T>
384bool equalAttrArgs(T *A1_B, T *A1_E, T *A2_B, T *A2_E,
386 if (A1_E - A1_B != A2_E - A2_B)
387 return false;
388
389 for (; A1_B != A1_E; ++A1_B, ++A2_B)
390 if (!equalAttrArgs(*A1_B, *A2_B, Context))
391 return false;
392
393 return true;
394}
395
396template <>
397bool equalAttrArgs<Attr *>(Attr *A1, Attr *A2,
399 if (!A1 || !A2)
400 return A1 == A2;
401 return A1->isEquivalent(*A2, Context);
402}
403
404template <>
405bool equalAttrArgs<Expr *>(Expr *A1, Expr *A2,
407 return ASTStructuralEquivalence::isEquivalent(Context, A1, A2);
408}
409
410static bool equalOMPAdjustArgsExprs(Expr *A, Expr *B,
412 if (!A || !B)
413 return A == B;
414 return equalAttrArgs(A, B, Context);
415}
416
417static bool equalOMPAdjustArgsBounds(const OMPAdjustArgsItem::Bound &A,
420 return A.Kind == B.Kind && A.IsSubtraction == B.IsSubtraction &&
421 equalOMPAdjustArgsExprs(A.E, B.E, Context);
422}
423
424static bool equalOMPAdjustArgsItems(const OMPAdjustArgsItem &A,
425 const OMPAdjustArgsItem &B,
427 return A.Kind == B.Kind && equalOMPAdjustArgsExprs(A.E, B.E, Context) &&
428 equalOMPAdjustArgsBounds(A.Lower, B.Lower, Context) &&
429 equalOMPAdjustArgsBounds(A.Upper, B.Upper, Context);
430}
431
432template <>
433bool equalAttrArgs<OMPAdjustArgsDescriptor *>(
436 if (A->AdjustOp != B->AdjustOp ||
438 A->items().size() != B->items().size())
439 return false;
440 for (unsigned I : llvm::seq<unsigned>(A->items().size()))
441 if (!equalOMPAdjustArgsItems(A->items()[I], B->items()[I], Context))
442 return false;
443 return true;
444}
445
446template <>
447bool equalAttrArgs<QualType>(QualType T1, QualType T2,
449 return ASTStructuralEquivalence::isEquivalent(Context, T1, T2);
450}
451
452template <>
453bool equalAttrArgs<const IdentifierInfo *>(
454 const IdentifierInfo *Name1, const IdentifierInfo *Name2,
456 return ASTStructuralEquivalence::isEquivalent(Name1, Name2);
457}
458
459bool areAlignedAttrsEqual(const AlignedAttr &A1, const AlignedAttr &A2,
461 if (A1.getSpelling() != A2.getSpelling())
462 return false;
463
464 if (A1.isAlignmentExpr() != A2.isAlignmentExpr())
465 return false;
466
467 if (A1.isAlignmentExpr())
468 return equalAttrArgs(A1.getAlignmentExpr(), A2.getAlignmentExpr(), Context);
469
470 return equalAttrArgs(A1.getAlignmentType()->getType(),
471 A2.getAlignmentType()->getType(), Context);
472}
473} // namespace
474
475namespace {
476// Machinery to unique attributes based on the arguments.
477// The construction mirrors the equivalent testing code above.
478// The content of the arguments are added to the FoldingSetNodeID instance,
479// which allows the AttributedTypes to unique the attributes based on
480// the value of the arguments.
481
482#define USE_DEFAULT_PROFILE \
483 (std::is_same_v<T, StringRef> || std::is_same_v<T, VersionTuple> || \
484 std::is_same_v<T, IdentifierInfo *> || \
485 std::is_same_v<T, const IdentifierInfo *> || std::is_enum_v<T> || \
486 std::is_integral_v<T>)
487
488template <class T>
489typename std::enable_if_t<!USE_DEFAULT_PROFILE>
490profileAttrArg(llvm::FoldingSetNodeID &, const ASTContext &, T) {
491 llvm_unreachable("profile not implemented for this type");
492}
493
494template <class T>
495typename std::enable_if_t<USE_DEFAULT_PROFILE>
496profileAttrArg(llvm::FoldingSetNodeID &ID, const ASTContext &, T V) {
497 if constexpr (std::is_same_v<T, StringRef>)
498 ID.AddString(V);
499 else if constexpr (std::is_same_v<T, VersionTuple>) {
500 ID.AddInteger(V.getMajor());
501 ID.AddInteger(V.getMinor().value_or(0));
502 ID.AddInteger(V.getSubminor().value_or(0));
503 ID.AddInteger(V.getBuild().value_or(0));
504 } else if constexpr (std::is_same_v<T, IdentifierInfo *> ||
505 std::is_same_v<T, const IdentifierInfo *>)
506 ID.AddPointer(V);
507 else
508 ID.AddInteger(static_cast<long long>(V));
509}
510
511template <>
512inline void profileAttrArg<ParamIdx>(llvm::FoldingSetNodeID &ID,
513 const ASTContext &, ParamIdx P) {
514 ID.AddBoolean(P.isValid());
515 if (P.isValid())
516 ID.AddInteger(P.getASTIndex());
517}
518
519template <class T>
520inline void profileAttrArg(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx,
521 T *Begin, T *End) {
522 ID.AddInteger(End - Begin);
523 for (; Begin != End; ++Begin)
524 profileAttrArg(ID, Ctx, *Begin);
525}
526
527template <>
528inline void profileAttrArg<Attr *>(llvm::FoldingSetNodeID &ID,
529 const ASTContext &Ctx, Attr *A) {
530 if (!A) {
531 ID.AddPointer(nullptr);
532 return;
533 }
534 ID.AddInteger(A->getKind());
535 A->Profile(ID, Ctx);
536}
537
538template <>
539inline void profileAttrArg<Expr *>(llvm::FoldingSetNodeID &ID,
540 const ASTContext &Ctx, Expr *E) {
541 E->Profile(ID, Ctx, /*Canonical=*/true);
542}
543
544static void profileOMPAdjustArgsExpr(llvm::FoldingSetNodeID &ID,
545 const ASTContext &Ctx, Expr *E) {
546 ID.AddBoolean(E != nullptr);
547 if (E)
548 profileAttrArg(ID, Ctx, E);
549}
550
551static void profileOMPAdjustArgsBound(llvm::FoldingSetNodeID &ID,
552 const ASTContext &Ctx,
553 const OMPAdjustArgsItem::Bound &Bound) {
554 ID.AddInteger(Bound.Kind);
555 ID.AddBoolean(Bound.IsSubtraction);
556 profileOMPAdjustArgsExpr(ID, Ctx, Bound.E);
557}
558
559static void profileOMPAdjustArgsItem(llvm::FoldingSetNodeID &ID,
560 const ASTContext &Ctx,
561 const OMPAdjustArgsItem &Item) {
562 ID.AddInteger(Item.Kind);
563 profileOMPAdjustArgsExpr(ID, Ctx, Item.E);
564 profileOMPAdjustArgsBound(ID, Ctx, Item.Lower);
565 profileOMPAdjustArgsBound(ID, Ctx, Item.Upper);
566}
567
568template <>
569inline void
570profileAttrArg<OMPAdjustArgsDescriptor *>(llvm::FoldingSetNodeID &ID,
571 const ASTContext &Ctx,
573 ID.AddInteger(Desc->AdjustOp);
574 ID.AddInteger(Desc->NeedDevicePtrModifier);
575 ID.AddInteger(Desc->items().size());
576 for (const OMPAdjustArgsItem &Item : Desc->items())
577 profileOMPAdjustArgsItem(ID, Ctx, Item);
578}
579
580template <>
581inline void profileAttrArg<QualType>(llvm::FoldingSetNodeID &ID,
582 const ASTContext &, QualType T) {
583 ID.AddPointer(T.getCanonicalType().getAsOpaquePtr());
584}
585
586void profileAlignedAttr(const AlignedAttr &A, llvm::FoldingSetNodeID &ID,
587 const ASTContext &Ctx) {
588 ID.AddInteger(A.getSpellingListIndex());
589 ID.AddBoolean(A.isAlignmentExpr());
590 if (A.isAlignmentExpr())
591 profileAttrArg(ID, Ctx, A.getAlignmentExpr());
592 else
593 profileAttrArg(ID, Ctx, A.getAlignmentType()->getType());
594}
595} // namespace
596
597#include "clang/AST/AttrImpl.inc"
Defines the clang::ASTContext interface.
#define V(N, I)
static StringRef getOptionName(StringRef Option, const char Delimiter='=')
Definition Clang.cpp:2313
This file defines OpenMP AST classes for clauses.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
unsigned getTargetDefaultAlignForAttributeAligned() const
Return the default alignment for attribute((aligned)) on this target, to be used if no alignment valu...
uint64_t getCharWidth() const
Return the size of the character type, in bits.
Attr - This represents one attribute.
Definition Attr.h:47
bool isEquivalent(const Attr &Other, StructuralEquivalenceContext &Context) const
attr::Kind getKind() const
Definition Attr.h:93
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) const
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
Definition CharUnits.h:155
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition DeclBase.h:568
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
Definition DeclBase.h:1067
This represents one expression.
Definition Expr.h:114
One of these records is kept for each identifier that is lexed.
Describes the source-level contents of one OpenMP 'adjust_args' clause.
ArrayRef< OMPAdjustArgsItem > items() const
OpenMPNeedDevicePtrModifier NeedDevicePtrModifier
OpenMPAdjustArgsOpKind AdjustOp
A single parameter index whose accessors require each use to make explicit the parameter index encodi...
Definition Attr.h:280
bool isValid() const
Is this parameter index valid?
Definition Attr.h:344
unsigned getASTIndex() const
Get the parameter index as it would normally be encoded at the AST level of representation: zero-orig...
Definition Attr.h:363
A (possibly-)qualified type.
Definition TypeBase.h:938
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const
Produce a unique representation of the given statement.
StringLiteral - This represents a string literal expression, e.g.
Definition Expr.h:1844
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:714
bool isEquivalent(StructuralEquivalenceContext &Context, QualType T1, QualType T2)
Determine structural equivalence of two types.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
Top level wrappers for InstallAPI frontend operations.
@ OMPC_NEED_DEVICE_PTR_unknown
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
const FunctionProtoType * T
@ OMPC_LINEAR_unknown
Definition OpenMPKinds.h:67
@ Full
Match, but we didn't check for full match.
const StreamingDiagnostic & operator<<(const StreamingDiagnostic &DB, const ConceptReference *C)
Insertion operator for diagnostics.
U cast(CodeGen::Address addr)
Definition Address.h:327
One bound of a parameter range.
Expr * E
The bound expression, or the logical offset for a NumArgs bound.
One item in an OpenMP 'adjust_args' parameter list.
Expr * E
A named parameter or positional expression for a Single item.
Describes how types, statements, expressions, and declarations should be printed.