clang 22.0.0git
SemaOpenACC.cpp
Go to the documentation of this file.
1//===--- SemaOpenACC.cpp - Semantic Analysis for OpenACC constructs -------===//
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/// \file
9/// This file implements semantic analysis for OpenACC constructs, and things
10/// that are not clause specific.
11///
12//===----------------------------------------------------------------------===//
13
21#include "clang/Sema/Scope.h"
22#include "clang/Sema/Sema.h"
23#include "llvm/ADT/StringExtras.h"
24#include "llvm/Support/Casting.h"
25
26using namespace clang;
27
28namespace {
29bool diagnoseConstructAppertainment(SemaOpenACC &S, OpenACCDirectiveKind K,
30 SourceLocation StartLoc, bool IsStmt) {
31 switch (K) {
32 default:
33 case OpenACCDirectiveKind::Invalid:
34 // Nothing to do here, both invalid and unimplemented don't really need to
35 // do anything.
36 break;
37 case OpenACCDirectiveKind::Parallel:
38 case OpenACCDirectiveKind::ParallelLoop:
39 case OpenACCDirectiveKind::Serial:
40 case OpenACCDirectiveKind::SerialLoop:
41 case OpenACCDirectiveKind::Kernels:
42 case OpenACCDirectiveKind::KernelsLoop:
43 case OpenACCDirectiveKind::Loop:
44 case OpenACCDirectiveKind::Data:
45 case OpenACCDirectiveKind::EnterData:
46 case OpenACCDirectiveKind::ExitData:
47 case OpenACCDirectiveKind::HostData:
48 case OpenACCDirectiveKind::Wait:
49 case OpenACCDirectiveKind::Update:
50 case OpenACCDirectiveKind::Init:
51 case OpenACCDirectiveKind::Shutdown:
52 case OpenACCDirectiveKind::Cache:
53 case OpenACCDirectiveKind::Atomic:
54 if (!IsStmt)
55 return S.Diag(StartLoc, diag::err_acc_construct_appertainment) << K;
56 break;
57 }
58 return false;
59}
60
61void CollectActiveReductionClauses(
63 ArrayRef<OpenACCClause *> CurClauses) {
64 for (auto *CurClause : CurClauses) {
65 if (auto *RedClause = dyn_cast<OpenACCReductionClause>(CurClause);
66 RedClause && !RedClause->getVarList().empty())
67 ActiveClauses.push_back(RedClause);
68 }
69}
70
71// Depth needs to be preserved for all associated statements that aren't
72// supposed to modify the compute/combined/loop construct information.
73bool PreserveLoopRAIIDepthInAssociatedStmtRAII(OpenACCDirectiveKind DK) {
74 switch (DK) {
75 case OpenACCDirectiveKind::Parallel:
76 case OpenACCDirectiveKind::ParallelLoop:
77 case OpenACCDirectiveKind::Serial:
78 case OpenACCDirectiveKind::SerialLoop:
79 case OpenACCDirectiveKind::Kernels:
80 case OpenACCDirectiveKind::KernelsLoop:
81 case OpenACCDirectiveKind::Loop:
82 return false;
83 case OpenACCDirectiveKind::Data:
84 case OpenACCDirectiveKind::HostData:
85 case OpenACCDirectiveKind::Atomic:
86 return true;
87 case OpenACCDirectiveKind::Cache:
88 case OpenACCDirectiveKind::Routine:
89 case OpenACCDirectiveKind::Declare:
90 case OpenACCDirectiveKind::EnterData:
91 case OpenACCDirectiveKind::ExitData:
92 case OpenACCDirectiveKind::Wait:
93 case OpenACCDirectiveKind::Init:
94 case OpenACCDirectiveKind::Shutdown:
95 case OpenACCDirectiveKind::Set:
96 case OpenACCDirectiveKind::Update:
97 llvm_unreachable("Doesn't have an associated stmt");
98 case OpenACCDirectiveKind::Invalid:
99 llvm_unreachable("Unhandled directive kind?");
100 }
101 llvm_unreachable("Unhandled directive kind?");
102}
103
104} // namespace
105
107
112 : SemaRef(S), OldActiveComputeConstructInfo(S.ActiveComputeConstructInfo),
113 DirKind(DK), OldLoopGangClauseOnKernel(S.LoopGangClauseOnKernel),
114 OldLoopWorkerClauseLoc(S.LoopWorkerClauseLoc),
115 OldLoopVectorClauseLoc(S.LoopVectorClauseLoc),
116 OldLoopWithoutSeqInfo(S.LoopWithoutSeqInfo),
117 ActiveReductionClauses(S.ActiveReductionClauses),
118 LoopRAII(SemaRef, PreserveLoopRAIIDepthInAssociatedStmtRAII(DirKind)) {
119
120 // Compute constructs end up taking their 'loop'.
121 if (DirKind == OpenACCDirectiveKind::Parallel ||
122 DirKind == OpenACCDirectiveKind::Serial ||
124 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
125 SemaRef.ActiveComputeConstructInfo.Kind = DirKind;
126 SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;
127
128 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
129 // construct, the gang clause behaves as follows. ... The region of a loop
130 // with a gang clause may not contain another loop with a gang clause unless
131 // within a nested compute region.
132 //
133 // Implement the 'unless within a nested compute region' part.
134 SemaRef.LoopGangClauseOnKernel = {};
135 SemaRef.LoopWorkerClauseLoc = {};
136 SemaRef.LoopVectorClauseLoc = {};
137 SemaRef.LoopWithoutSeqInfo = {};
138 } else if (DirKind == OpenACCDirectiveKind::ParallelLoop ||
141 SemaRef.ActiveComputeConstructInfo.Kind = DirKind;
142 SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;
143
144 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
145 SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
146 SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
147
148 SemaRef.LoopGangClauseOnKernel = {};
149 SemaRef.LoopWorkerClauseLoc = {};
150 SemaRef.LoopVectorClauseLoc = {};
151
152 // Set the active 'loop' location if there isn't a 'seq' on it, so we can
153 // diagnose the for loops.
154 SemaRef.LoopWithoutSeqInfo = {};
155 if (Clauses.end() ==
156 llvm::find_if(Clauses, llvm::IsaPred<OpenACCSeqClause>))
157 SemaRef.LoopWithoutSeqInfo = {DirKind, DirLoc};
158
159 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
160 // construct, the gang clause behaves as follows. ... The region of a loop
161 // with a gang clause may not contain another loop with a gang clause unless
162 // within a nested compute region.
163 //
164 // We don't bother doing this when this is a template instantiation, as
165 // there is no reason to do these checks: the existance of a
166 // gang/kernels/etc cannot be dependent.
167 if (DirKind == OpenACCDirectiveKind::KernelsLoop && UnInstClauses.empty()) {
168 // This handles the 'outer loop' part of this.
169 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCGangClause>);
170 if (Itr != Clauses.end())
171 SemaRef.LoopGangClauseOnKernel = {(*Itr)->getBeginLoc(), DirKind};
172 }
173
174 if (UnInstClauses.empty()) {
175 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCWorkerClause>);
176 if (Itr != Clauses.end())
177 SemaRef.LoopWorkerClauseLoc = (*Itr)->getBeginLoc();
178
179 auto *Itr2 = llvm::find_if(Clauses, llvm::IsaPred<OpenACCVectorClause>);
180 if (Itr2 != Clauses.end())
181 SemaRef.LoopVectorClauseLoc = (*Itr2)->getBeginLoc();
182 }
183 } else if (DirKind == OpenACCDirectiveKind::Loop) {
184 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
185 SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
186 SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
187
188 // Set the active 'loop' location if there isn't a 'seq' on it, so we can
189 // diagnose the for loops.
190 SemaRef.LoopWithoutSeqInfo = {};
191 if (Clauses.end() ==
192 llvm::find_if(Clauses, llvm::IsaPred<OpenACCSeqClause>))
193 SemaRef.LoopWithoutSeqInfo = {DirKind, DirLoc};
194
195 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
196 // construct, the gang clause behaves as follows. ... The region of a loop
197 // with a gang clause may not contain another loop with a gang clause unless
198 // within a nested compute region.
199 //
200 // We don't bother doing this when this is a template instantiation, as
201 // there is no reason to do these checks: the existance of a
202 // gang/kernels/etc cannot be dependent.
203 if (SemaRef.getActiveComputeConstructInfo().Kind ==
205 UnInstClauses.empty()) {
206 // This handles the 'outer loop' part of this.
207 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCGangClause>);
208 if (Itr != Clauses.end())
209 SemaRef.LoopGangClauseOnKernel = {(*Itr)->getBeginLoc(),
211 }
212
213 if (UnInstClauses.empty()) {
214 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCWorkerClause>);
215 if (Itr != Clauses.end())
216 SemaRef.LoopWorkerClauseLoc = (*Itr)->getBeginLoc();
217
218 auto *Itr2 = llvm::find_if(Clauses, llvm::IsaPred<OpenACCVectorClause>);
219 if (Itr2 != Clauses.end())
220 SemaRef.LoopVectorClauseLoc = (*Itr2)->getBeginLoc();
221 }
222 }
223}
224
225namespace {
226// Given two collapse clauses, and the uninstanted version of the new one,
227// return the 'best' one for the purposes of setting the collapse checking
228// values.
230getBestCollapseCandidate(const OpenACCCollapseClause *Old,
232 const OpenACCCollapseClause *UnInstNew) {
233 // If the loop count is nullptr, it is because instantiation failed, so this
234 // can't be the best one.
235 if (!New->getLoopCount())
236 return Old;
237
238 // If the loop-count had an error, than 'new' isn't a candidate.
239 if (!New->getLoopCount())
240 return Old;
241
242 // Don't consider uninstantiated ones, since we can't really check these.
243 if (New->getLoopCount()->isInstantiationDependent())
244 return Old;
245
246 // If this is an instantiation, and the old version wasn't instantation
247 // dependent, than nothing has changed and we've already done a diagnostic
248 // based on this one, so don't consider it.
249 if (UnInstNew && !UnInstNew->getLoopCount()->isInstantiationDependent())
250 return Old;
251
252 // New is now a valid candidate, so if there isn't an old one at this point,
253 // New is the only valid one.
254 if (!Old)
255 return New;
256
257 // If the 'New' expression has a larger value than 'Old', then it is the new
258 // best candidate.
259 if (cast<ConstantExpr>(Old->getLoopCount())->getResultAsAPSInt() <
260 cast<ConstantExpr>(New->getLoopCount())->getResultAsAPSInt())
261 return New;
262
263 return Old;
264}
265} // namespace
266
270
271 // Reset this checking for loops that aren't covered in a RAII object.
272 SemaRef.LoopInfo.CurLevelHasLoopAlready = false;
273 SemaRef.CollapseInfo.CollapseDepthSatisfied = true;
274 SemaRef.CollapseInfo.CurCollapseCount = 0;
275 SemaRef.TileInfo.TileDepthSatisfied = true;
276
277 // We make sure to take an optional list of uninstantiated clauses, so that
278 // we can check to make sure we don't 'double diagnose' in the event that
279 // the value of 'N' was not dependent in a template. Since we cannot count on
280 // there only being a single collapse clause, we count on the order to make
281 // sure get the matching ones, and we count on TreeTransform not removing
282 // these, even if loop-count instantiation failed. We can check the
283 // non-dependent ones right away, and realize that subsequent instantiation
284 // can only make it more specific.
285
286 auto *UnInstClauseItr =
287 llvm::find_if(UnInstClauses, llvm::IsaPred<OpenACCCollapseClause>);
288 auto *ClauseItr =
289 llvm::find_if(Clauses, llvm::IsaPred<OpenACCCollapseClause>);
290 const OpenACCCollapseClause *FoundClause = nullptr;
291
292 // Loop through the list of Collapse clauses and find the one that:
293 // 1- Has a non-dependent, non-null loop count (null means error, likely
294 // during instantiation).
295 // 2- If UnInstClauses isn't empty, its corresponding
296 // loop count was dependent.
297 // 3- Has the largest 'loop count' of all.
298 while (ClauseItr != Clauses.end()) {
299 const OpenACCCollapseClause *CurClause =
300 cast<OpenACCCollapseClause>(*ClauseItr);
301 const OpenACCCollapseClause *UnInstCurClause =
302 UnInstClauseItr == UnInstClauses.end()
303 ? nullptr
304 : cast<OpenACCCollapseClause>(*UnInstClauseItr);
305
306 FoundClause =
307 getBestCollapseCandidate(FoundClause, CurClause, UnInstCurClause);
308
309 UnInstClauseItr =
310 UnInstClauseItr == UnInstClauses.end()
311 ? UnInstClauseItr
312 : std::find_if(std::next(UnInstClauseItr), UnInstClauses.end(),
313 llvm::IsaPred<OpenACCCollapseClause>);
314 ClauseItr = std::find_if(std::next(ClauseItr), Clauses.end(),
315 llvm::IsaPred<OpenACCCollapseClause>);
316 }
317
318 if (!FoundClause)
319 return;
320
321 SemaRef.CollapseInfo.ActiveCollapse = FoundClause;
322 SemaRef.CollapseInfo.CollapseDepthSatisfied = false;
323 SemaRef.CollapseInfo.CurCollapseCount =
324 cast<ConstantExpr>(FoundClause->getLoopCount())->getResultAsAPSInt();
325 SemaRef.CollapseInfo.DirectiveKind = DirKind;
326}
327
331 // We don't diagnose if this is during instantiation, since the only thing we
332 // care about is the number of arguments, which we can figure out without
333 // instantiation, so we don't want to double-diagnose.
334 if (UnInstClauses.size() > 0)
335 return;
336 auto *TileClauseItr =
337 llvm::find_if(Clauses, llvm::IsaPred<OpenACCTileClause>);
338
339 if (Clauses.end() == TileClauseItr)
340 return;
341
342 OpenACCTileClause *TileClause = cast<OpenACCTileClause>(*TileClauseItr);
343
344 // Multiple tile clauses are allowed, so ensure that we use the one with the
345 // largest 'tile count'.
346 while (Clauses.end() !=
347 (TileClauseItr = std::find_if(std::next(TileClauseItr), Clauses.end(),
348 llvm::IsaPred<OpenACCTileClause>))) {
349 OpenACCTileClause *NewClause = cast<OpenACCTileClause>(*TileClauseItr);
350 if (NewClause->getSizeExprs().size() > TileClause->getSizeExprs().size())
351 TileClause = NewClause;
352 }
353
354 SemaRef.TileInfo.ActiveTile = TileClause;
355 SemaRef.TileInfo.TileDepthSatisfied = false;
356 SemaRef.TileInfo.CurTileCount =
357 static_cast<unsigned>(TileClause->getSizeExprs().size());
358 SemaRef.TileInfo.DirectiveKind = DirKind;
359}
360
362 if (DirKind == OpenACCDirectiveKind::Parallel ||
363 DirKind == OpenACCDirectiveKind::Serial ||
365 DirKind == OpenACCDirectiveKind::Loop ||
369 SemaRef.ActiveComputeConstructInfo = OldActiveComputeConstructInfo;
370 SemaRef.LoopGangClauseOnKernel = OldLoopGangClauseOnKernel;
371 SemaRef.LoopWorkerClauseLoc = OldLoopWorkerClauseLoc;
372 SemaRef.LoopVectorClauseLoc = OldLoopVectorClauseLoc;
373 SemaRef.LoopWithoutSeqInfo = OldLoopWithoutSeqInfo;
374 SemaRef.ActiveReductionClauses.swap(ActiveReductionClauses);
375 } else if (DirKind == OpenACCDirectiveKind::Data ||
377 // Intentionally doesn't reset the Loop, Compute Construct, or reduction
378 // effects.
379 }
380}
381
383 SourceLocation DirLoc) {
384 // Start an evaluation context to parse the clause arguments on.
387
388 // There is nothing do do here as all we have at this point is the name of the
389 // construct itself.
390}
391
394 Expr *IntExpr) {
395
396 assert(((DK != OpenACCDirectiveKind::Invalid &&
402 "Only one of directive or clause kind should be provided");
403
404 class IntExprConverter : public Sema::ICEConvertDiagnoser {
405 OpenACCDirectiveKind DirectiveKind;
406 OpenACCClauseKind ClauseKind;
407 Expr *IntExpr;
408
409 // gets the index into the diagnostics so we can use this for clauses,
410 // directives, and sub array.s
411 unsigned getDiagKind() const {
412 if (ClauseKind != OpenACCClauseKind::Invalid)
413 return 0;
414 if (DirectiveKind != OpenACCDirectiveKind::Invalid)
415 return 1;
416 return 2;
417 }
418
419 public:
420 IntExprConverter(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
421 Expr *IntExpr)
422 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false,
423 /*Suppress=*/false,
424 /*SuppressConversion=*/true),
425 DirectiveKind(DK), ClauseKind(CK), IntExpr(IntExpr) {}
426
427 bool match(QualType T) override {
428 // OpenACC spec just calls this 'integer expression' as having an
429 // 'integer type', so fall back on C99's 'integer type'.
430 return T->isIntegerType();
431 }
433 QualType T) override {
434 return S.Diag(Loc, diag::err_acc_int_expr_requires_integer)
435 << getDiagKind() << ClauseKind << DirectiveKind << T;
436 }
437
439 diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) override {
440 return S.Diag(Loc, diag::err_acc_int_expr_incomplete_class_type)
441 << T << IntExpr->getSourceRange();
442 }
443
445 diagnoseExplicitConv(Sema &S, SourceLocation Loc, QualType T,
446 QualType ConvTy) override {
447 return S.Diag(Loc, diag::err_acc_int_expr_explicit_conversion)
448 << T << ConvTy;
449 }
450
451 SemaBase::SemaDiagnosticBuilder noteExplicitConv(Sema &S,
452 CXXConversionDecl *Conv,
453 QualType ConvTy) override {
454 return S.Diag(Conv->getLocation(), diag::note_acc_int_expr_conversion)
455 << ConvTy->isEnumeralType() << ConvTy;
456 }
457
459 diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) override {
460 return S.Diag(Loc, diag::err_acc_int_expr_multiple_conversions) << T;
461 }
462
464 noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
465 return S.Diag(Conv->getLocation(), diag::note_acc_int_expr_conversion)
466 << ConvTy->isEnumeralType() << ConvTy;
467 }
468
470 diagnoseConversion(Sema &S, SourceLocation Loc, QualType T,
471 QualType ConvTy) override {
472 llvm_unreachable("conversion functions are permitted");
473 }
474 } IntExprDiagnoser(DK, CK, IntExpr);
475
476 if (!IntExpr)
477 return ExprError();
478
480 Loc, IntExpr, IntExprDiagnoser);
481 if (IntExprResult.isInvalid())
482 return ExprError();
483
484 IntExpr = IntExprResult.get();
485 if (!IntExpr->isTypeDependent() && !IntExpr->getType()->isIntegerType())
486 return ExprError();
487
488 // TODO OpenACC: Do we want to perform usual unary conversions here? When
489 // doing codegen we might find that is necessary, but skip it for now.
490 return IntExpr;
491}
492
494 Expr *VarExpr) {
495 // We already know that VarExpr is a proper reference to a variable, so we
496 // should be able to just take the type of the expression to get the type of
497 // the referenced variable.
498
499 // We've already seen an error, don't diagnose anything else.
500 if (!VarExpr || VarExpr->containsErrors())
501 return false;
502
503 if (isa<ArraySectionExpr>(VarExpr->IgnoreParenImpCasts()) ||
504 VarExpr->hasPlaceholderType(BuiltinType::ArraySection)) {
505 Diag(VarExpr->getExprLoc(), diag::err_array_section_use) << /*OpenACC=*/0;
506 Diag(VarExpr->getExprLoc(), diag::note_acc_expected_pointer_var);
507 return true;
508 }
509
510 QualType Ty = VarExpr->getType();
512
513 // Nothing we can do if this is a dependent type.
514 if (Ty->isDependentType())
515 return false;
516
517 if (!Ty->isPointerType())
518 return Diag(VarExpr->getExprLoc(), diag::err_acc_var_not_pointer_type)
519 << ClauseKind << Ty;
520 return false;
521}
522
525 if (DK == OpenACCDirectiveKind::Cache) {
526 CacheInfo.ParsingCacheVarList = true;
527 CacheInfo.IsInvalidCacheRef = false;
528 }
529}
530
532 CacheInfo.ParsingCacheVarList = false;
533 CacheInfo.IsInvalidCacheRef = false;
534}
535
537 Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts();
538 // Clear this here, so we can do the returns based on the invalid cache ref
539 // here. Note all return statements in this function must return ExprError if
540 // IsInvalidCacheRef. However, instead of doing an 'early return' in that
541 // case, we can let the rest of the diagnostics happen, as the invalid decl
542 // ref is a warning.
543 bool WasParsingInvalidCacheRef =
544 CacheInfo.ParsingCacheVarList && CacheInfo.IsInvalidCacheRef;
545 CacheInfo.ParsingCacheVarList = false;
546 CacheInfo.IsInvalidCacheRef = false;
547
548 if (!isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) {
549 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_cache);
550 return ExprError();
551 }
552
553 // It isn't clear what 'simple array element or simple subarray' means, so we
554 // will just allow arbitrary depth.
555 while (isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) {
556 if (auto *SubScrpt = dyn_cast<ArraySubscriptExpr>(CurVarExpr))
557 CurVarExpr = SubScrpt->getBase()->IgnoreParenImpCasts();
558 else
559 CurVarExpr =
560 cast<ArraySectionExpr>(CurVarExpr)->getBase()->IgnoreParenImpCasts();
561 }
562
563 // References to a VarDecl are fine.
564 if (const auto *DRE = dyn_cast<DeclRefExpr>(CurVarExpr)) {
565 if (isa<VarDecl, NonTypeTemplateParmDecl>(
566 DRE->getFoundDecl()->getCanonicalDecl()))
567 return WasParsingInvalidCacheRef ? ExprEmpty() : VarExpr;
568 }
569
570 if (const auto *ME = dyn_cast<MemberExpr>(CurVarExpr)) {
571 if (isa<FieldDecl>(ME->getMemberDecl()->getCanonicalDecl())) {
572 return WasParsingInvalidCacheRef ? ExprEmpty() : VarExpr;
573 }
574 }
575
576 // Nothing really we can do here, as these are dependent. So just return they
577 // are valid.
578 if (isa<DependentScopeDeclRefExpr, CXXDependentScopeMemberExpr>(CurVarExpr))
579 return WasParsingInvalidCacheRef ? ExprEmpty() : VarExpr;
580
581 // There isn't really anything we can do in the case of a recovery expr, so
582 // skip the diagnostic rather than produce a confusing diagnostic.
583 if (isa<RecoveryExpr>(CurVarExpr))
584 return ExprError();
585
586 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_cache);
587 return ExprError();
588}
589
591 if (!getLangOpts().OpenACC || !CacheInfo.ParsingCacheVarList || !D ||
592 D->isInvalidDecl())
593 return;
594 // A 'cache' variable reference MUST be declared before the 'acc.loop' we
595 // generate in codegen, so we have to mark it invalid here in some way. We do
596 // so in a bit of a convoluted way as there is no good way to put this into
597 // the AST, so we store it in SemaOpenACC State. We can check the Scope
598 // during parsing to make sure there is a 'loop' before the decl is
599 // declared(and skip during instantiation).
600 // We only diagnose this as a warning, as this isn't required by the standard
601 // (unless you take a VERY awkward reading of some awkward prose).
602
603 Scope *CurScope = SemaRef.getCurScope();
604
605 // if we are at TU level, we are either doing some EXTRA wacky, or are in a
606 // template instantiation, so just give up.
607 if (CurScope->getDepth() == 0)
608 return;
609
610 while (CurScope) {
611 // If we run into a loop construct scope, than this is 'correct' in that the
612 // declaration is outside of the loop.
613 if (CurScope->isOpenACCLoopConstructScope())
614 return;
615
616 if (CurScope->isDeclScope(D)) {
617 Diag(Loc, diag::warn_acc_cache_var_not_outside_loop);
618
619 CacheInfo.IsInvalidCacheRef = true;
620 }
621
622 CurScope = CurScope->getParent();
623 }
624 // If we don't find the decl at all, we assume that it must be outside of the
625 // loop (or we aren't in a loop!) so skip the diagnostic.
626}
627
628namespace {
629// Check whether the type of the thing we are referencing is OK for things like
630// private, firstprivate, and reduction, which require certain operators to be
631// available.
632ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr,
633 SourceLocation InnerLoc, QualType InnerTy) {
634 // There is nothing to do here, only these three have these sorts of
635 // restrictions.
636 if (CK != OpenACCClauseKind::Private &&
639 return VarExpr;
640
641 // We can't test this if it isn't here, or if the type isn't clear yet.
642 if (InnerTy.isNull() || InnerTy->isDependentType())
643 return VarExpr;
644
645 InnerTy = InnerTy.getUnqualifiedType();
646 if (auto *RefTy = InnerTy->getAs<ReferenceType>())
647 InnerTy = RefTy->getPointeeType();
648
649 if (auto *ArrTy = InnerTy->getAsArrayTypeUnsafe()) {
650 // Non constant arrays decay to 'pointer', so warn and return that we're
651 // successful.
652 if (!ArrTy->isConstantArrayType()) {
653 S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_non_const_array)
654 << InnerTy << CK;
655 return VarExpr;
656 }
657
658 return CheckVarType(S, CK, VarExpr, InnerLoc, ArrTy->getElementType());
659 }
660
661 auto *RD = InnerTy->getAsCXXRecordDecl();
662
663 // if this isn't a C++ record decl, we can create/copy/destroy this thing at
664 // will without problem, so this is a success.
665 if (!RD)
666 return VarExpr;
667
668 if (CK == OpenACCClauseKind::Private) {
669 bool HasNonDeletedDefaultCtor =
670 llvm::find_if(RD->ctors(), [](const CXXConstructorDecl *CD) {
671 return CD->isDefaultConstructor() && !CD->isDeleted();
672 }) != RD->ctors().end();
673 if (!HasNonDeletedDefaultCtor && !RD->needsImplicitDefaultConstructor()) {
674 S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_lacks_op)
675 << InnerTy << CK << clang::diag::AccVarReferencedReason::DefCtor;
676 return ExprError();
677 }
678 } else if (CK == OpenACCClauseKind::FirstPrivate) {
679 if (!RD->hasSimpleCopyConstructor()) {
681 RD, CXXSpecialMemberKind::CopyConstructor, /*ConstArg=*/true,
682 /*VolatileArg=*/false, /*RValueThis=*/false, /*ConstThis=*/false,
683 /*VolatileThis=*/false);
684
686 SMOR.getMethod()->isDeleted()) {
687 S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_lacks_op)
688 << InnerTy << CK << clang::diag::AccVarReferencedReason::CopyCtor;
689 return ExprError();
690 }
691 }
692 } else if (CK == OpenACCClauseKind::Reduction) {
693 // TODO: Reduction needs to be an aggregate, which gets checked later, so
694 // construction here isn't a problem. However, we need to make sure that we
695 // can compare it correctly still.
696 }
697
698 // All 3 things need to make sure they have a dtor.
699 bool DestructorDeleted =
700 RD->getDestructor() && RD->getDestructor()->isDeleted();
701 if (DestructorDeleted && !RD->needsImplicitDestructor()) {
702 S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_lacks_op)
703 << InnerTy << CK << clang::diag::AccVarReferencedReason::Dtor;
704 return ExprError();
705 }
706 return VarExpr;
707}
708
709ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr,
710 Expr *InnerExpr) {
711 if (!InnerExpr)
712 return VarExpr;
713 return CheckVarType(S, CK, VarExpr, InnerExpr->getBeginLoc(),
714 InnerExpr->getType());
715}
716} // namespace
717
719 Expr *VarExpr) {
720 // This has unique enough restrictions that we should split it to a separate
721 // function.
723 return ActOnCacheVar(VarExpr);
724
725 Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts();
726
727 // 'use_device' doesn't allow array subscript or array sections.
728 // OpenACC3.3 2.8:
729 // A 'var' in a 'use_device' clause must be the name of a variable or array.
730 // OpenACC3.3 2.13:
731 // A 'var' in a 'declare' directive must be a variable or array name.
732 if ((CK == OpenACCClauseKind::UseDevice ||
734 if (isa<ArraySubscriptExpr>(CurVarExpr)) {
735 Diag(VarExpr->getExprLoc(),
736 diag::err_acc_not_a_var_ref_use_device_declare)
738 return ExprError();
739 }
740 // As an extension, we allow 'array sections'/'sub-arrays' here, as that is
741 // effectively defining an array, and are in common use.
742 if (isa<ArraySectionExpr>(CurVarExpr))
743 Diag(VarExpr->getExprLoc(),
744 diag::ext_acc_array_section_use_device_declare)
746 }
747
748 // Sub-arrays/subscript-exprs are fine as long as the base is a
749 // VarExpr/MemberExpr. So strip all of those off.
750 while (isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) {
751 if (auto *SubScrpt = dyn_cast<ArraySubscriptExpr>(CurVarExpr))
752 CurVarExpr = SubScrpt->getBase()->IgnoreParenImpCasts();
753 else
754 CurVarExpr =
755 cast<ArraySectionExpr>(CurVarExpr)->getBase()->IgnoreParenImpCasts();
756 }
757
758 // References to a VarDecl are fine.
759 if (const auto *DRE = dyn_cast<DeclRefExpr>(CurVarExpr)) {
760 if (isa<VarDecl, NonTypeTemplateParmDecl>(
761 DRE->getFoundDecl()->getCanonicalDecl()))
762 return CheckVarType(*this, CK, VarExpr, CurVarExpr);
763 }
764
765 // If CK is a Reduction, this special cases for OpenACC3.3 2.5.15: "A var in a
766 // reduction clause must be a scalar variable name, an aggregate variable
767 // name, an array element, or a subarray.
768 // If CK is a 'use_device', this also isn't valid, as it isn't the name of a
769 // variable or array, if not done as a member expr.
770 // A MemberExpr that references a Field is valid for other clauses.
771 if (const auto *ME = dyn_cast<MemberExpr>(CurVarExpr)) {
772 if (isa<FieldDecl>(ME->getMemberDecl()->getCanonicalDecl())) {
776
777 // We can allow 'member expr' if the 'this' is implicit in the case of
778 // declare, reduction, and use_device.
779 const auto *This = dyn_cast<CXXThisExpr>(ME->getBase());
780 if (This && This->isImplicit())
781 return CheckVarType(*this, CK, VarExpr, CurVarExpr);
782 } else {
783 return CheckVarType(*this, CK, VarExpr, CurVarExpr);
784 }
785 }
786 }
787
788 // Referring to 'this' is ok for the most part, but for 'use_device'/'declare'
789 // doesn't fall into 'variable or array name'
791 DK != OpenACCDirectiveKind::Declare && isa<CXXThisExpr>(CurVarExpr))
792 return CheckVarType(*this, CK, VarExpr, CurVarExpr);
793
794 // Nothing really we can do here, as these are dependent. So just return they
795 // are valid.
796 if (isa<DependentScopeDeclRefExpr>(CurVarExpr) ||
798 isa<CXXDependentScopeMemberExpr>(CurVarExpr)))
799 return CheckVarType(*this, CK, VarExpr, CurVarExpr);
800
801 // There isn't really anything we can do in the case of a recovery expr, so
802 // skip the diagnostic rather than produce a confusing diagnostic.
803 if (isa<RecoveryExpr>(CurVarExpr))
804 return ExprError();
805
807 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device_declare)
808 << /*declare*/ 1;
809 else if (CK == OpenACCClauseKind::UseDevice)
810 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device_declare)
811 << /*use_device*/ 0;
812 else
813 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref)
815 return ExprError();
816}
817
819 Expr *LowerBound,
820 SourceLocation ColonLoc,
821 Expr *Length,
822 SourceLocation RBLoc) {
823 ASTContext &Context = getASTContext();
824
825 // Handle placeholders.
826 if (Base->hasPlaceholderType() &&
827 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
829 if (Result.isInvalid())
830 return ExprError();
831 Base = Result.get();
832 }
833 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
835 if (Result.isInvalid())
836 return ExprError();
838 if (Result.isInvalid())
839 return ExprError();
840 LowerBound = Result.get();
841 }
842 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
844 if (Result.isInvalid())
845 return ExprError();
847 if (Result.isInvalid())
848 return ExprError();
849 Length = Result.get();
850 }
851
852 // Check the 'base' value, it must be an array or pointer type, and not to/of
853 // a function type.
855 QualType ResultTy;
856 if (!Base->isTypeDependent()) {
857 if (OriginalBaseTy->isAnyPointerType()) {
858 ResultTy = OriginalBaseTy->getPointeeType();
859 } else if (OriginalBaseTy->isArrayType()) {
860 ResultTy = OriginalBaseTy->getAsArrayTypeUnsafe()->getElementType();
861 } else {
862 return ExprError(
863 Diag(Base->getExprLoc(), diag::err_acc_typecheck_subarray_value)
864 << Base->getSourceRange());
865 }
866
867 if (ResultTy->isFunctionType()) {
868 Diag(Base->getExprLoc(), diag::err_acc_subarray_function_type)
869 << ResultTy << Base->getSourceRange();
870 return ExprError();
871 }
872
873 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
874 diag::err_acc_subarray_incomplete_type,
875 Base))
876 return ExprError();
877
878 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
880 if (Result.isInvalid())
881 return ExprError();
882 Base = Result.get();
883 }
884 }
885
886 auto GetRecovery = [&](Expr *E, QualType Ty) {
887 ExprResult Recovery =
889 return Recovery.isUsable() ? Recovery.get() : nullptr;
890 };
891
892 // Ensure both of the expressions are int-exprs.
893 if (LowerBound && !LowerBound->isTypeDependent()) {
894 ExprResult LBRes =
896 LowerBound->getExprLoc(), LowerBound);
897
898 if (LBRes.isUsable())
899 LBRes = SemaRef.DefaultLvalueConversion(LBRes.get());
900 LowerBound =
901 LBRes.isUsable() ? LBRes.get() : GetRecovery(LowerBound, Context.IntTy);
902 }
903
904 if (Length && !Length->isTypeDependent()) {
905 ExprResult LenRes =
907 Length->getExprLoc(), Length);
908
909 if (LenRes.isUsable())
910 LenRes = SemaRef.DefaultLvalueConversion(LenRes.get());
911 Length =
912 LenRes.isUsable() ? LenRes.get() : GetRecovery(Length, Context.IntTy);
913 }
914
915 // Length is required if the base type is not an array of known bounds.
916 if (!Length && (OriginalBaseTy.isNull() ||
917 (!OriginalBaseTy->isDependentType() &&
918 !OriginalBaseTy->isConstantArrayType() &&
919 !OriginalBaseTy->isDependentSizedArrayType()))) {
920 bool IsArray = !OriginalBaseTy.isNull() && OriginalBaseTy->isArrayType();
921 SourceLocation DiagLoc = ColonLoc.isInvalid() ? LBLoc : ColonLoc;
922 Diag(DiagLoc, diag::err_acc_subarray_no_length) << IsArray;
923 // Fill in a dummy 'length' so that when we instantiate this we don't
924 // double-diagnose here.
926 DiagLoc, SourceLocation(), ArrayRef<Expr *>(), Context.IntTy);
927 Length = Recovery.isUsable() ? Recovery.get() : nullptr;
928 }
929
930 // Check the values of each of the arguments, they cannot be negative(we
931 // assume), and if the array bound is known, must be within range. As we do
932 // so, do our best to continue with evaluation, we can set the
933 // value/expression to nullptr/nullopt if they are invalid, and treat them as
934 // not present for the rest of evaluation.
935
936 // We don't have to check for dependence, because the dependent size is
937 // represented as a different AST node.
938 std::optional<llvm::APSInt> BaseSize;
939 if (!OriginalBaseTy.isNull() && OriginalBaseTy->isConstantArrayType()) {
940 const auto *ArrayTy = Context.getAsConstantArrayType(OriginalBaseTy);
941 BaseSize = ArrayTy->getSize();
942 }
943
944 auto GetBoundValue = [&](Expr *E) -> std::optional<llvm::APSInt> {
945 if (!E || E->isInstantiationDependent())
946 return std::nullopt;
947
949 if (!E->EvaluateAsInt(Res, Context))
950 return std::nullopt;
951 return Res.Val.getInt();
952 };
953
954 std::optional<llvm::APSInt> LowerBoundValue = GetBoundValue(LowerBound);
955 std::optional<llvm::APSInt> LengthValue = GetBoundValue(Length);
956
957 // Check lower bound for negative or out of range.
958 if (LowerBoundValue.has_value()) {
959 if (LowerBoundValue->isNegative()) {
960 Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_negative)
961 << /*LowerBound=*/0 << toString(*LowerBoundValue, /*Radix=*/10);
962 LowerBoundValue.reset();
963 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
964 } else if (BaseSize.has_value() &&
965 llvm::APSInt::compareValues(*LowerBoundValue, *BaseSize) >= 0) {
966 // Lower bound (start index) must be less than the size of the array.
967 Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_out_of_range)
968 << /*LowerBound=*/0 << toString(*LowerBoundValue, /*Radix=*/10)
969 << toString(*BaseSize, /*Radix=*/10);
970 LowerBoundValue.reset();
971 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
972 }
973 }
974
975 // Check length for negative or out of range.
976 if (LengthValue.has_value()) {
977 if (LengthValue->isNegative()) {
978 Diag(Length->getExprLoc(), diag::err_acc_subarray_negative)
979 << /*Length=*/1 << toString(*LengthValue, /*Radix=*/10);
980 LengthValue.reset();
981 Length = GetRecovery(Length, Length->getType());
982 } else if (BaseSize.has_value() &&
983 llvm::APSInt::compareValues(*LengthValue, *BaseSize) > 0) {
984 // Length must be lessthan or EQUAL to the size of the array.
985 Diag(Length->getExprLoc(), diag::err_acc_subarray_out_of_range)
986 << /*Length=*/1 << toString(*LengthValue, /*Radix=*/10)
987 << toString(*BaseSize, /*Radix=*/10);
988 LengthValue.reset();
989 Length = GetRecovery(Length, Length->getType());
990 }
991 }
992
993 // Adding two APSInts requires matching sign, so extract that here.
994 auto AddAPSInt = [](llvm::APSInt LHS, llvm::APSInt RHS) -> llvm::APSInt {
995 if (LHS.isSigned() == RHS.isSigned())
996 return LHS + RHS;
997
998 unsigned Width = std::max(LHS.getBitWidth(), RHS.getBitWidth()) + 1;
999 return llvm::APSInt(LHS.sext(Width) + RHS.sext(Width), /*Signed=*/true);
1000 };
1001
1002 // If we know all 3 values, we can diagnose that the total value would be out
1003 // of range.
1004 if (BaseSize.has_value() && LowerBoundValue.has_value() &&
1005 LengthValue.has_value() &&
1006 llvm::APSInt::compareValues(AddAPSInt(*LowerBoundValue, *LengthValue),
1007 *BaseSize) > 0) {
1008 Diag(Base->getExprLoc(),
1009 diag::err_acc_subarray_base_plus_length_out_of_range)
1010 << toString(*LowerBoundValue, /*Radix=*/10)
1011 << toString(*LengthValue, /*Radix=*/10)
1012 << toString(*BaseSize, /*Radix=*/10);
1013
1014 LowerBoundValue.reset();
1015 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
1016 LengthValue.reset();
1017 Length = GetRecovery(Length, Length->getType());
1018 }
1019
1020 // If any part of the expression is dependent, return a dependent sub-array.
1021 QualType ArrayExprTy = Context.ArraySectionTy;
1022 if (Base->isTypeDependent() ||
1023 (LowerBound && LowerBound->isInstantiationDependent()) ||
1024 (Length && Length->isInstantiationDependent()))
1025 ArrayExprTy = Context.DependentTy;
1026
1027 return new (Context)
1028 ArraySectionExpr(Base, LowerBound, Length, ArrayExprTy, VK_LValue,
1029 OK_Ordinary, ColonLoc, RBLoc);
1030}
1031
1033 if (!getLangOpts().OpenACC)
1034 return;
1035
1036 if (!LoopInfo.TopLevelLoopSeen)
1037 return;
1038
1039 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
1040 Diag(WhileLoc, diag::err_acc_invalid_in_loop)
1041 << /*while loop*/ 1 << CollapseInfo.DirectiveKind
1043 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
1044 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1045 diag::note_acc_active_clause_here)
1047
1048 // Remove the value so that we don't get cascading errors in the body. The
1049 // caller RAII object will restore this.
1050 CollapseInfo.CurCollapseCount = std::nullopt;
1051 }
1052
1053 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
1054 Diag(WhileLoc, diag::err_acc_invalid_in_loop)
1055 << /*while loop*/ 1 << TileInfo.DirectiveKind
1057 assert(TileInfo.ActiveTile && "tile count without object?");
1058 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
1060
1061 // Remove the value so that we don't get cascading errors in the body. The
1062 // caller RAII object will restore this.
1063 TileInfo.CurTileCount = std::nullopt;
1064 }
1065}
1066
1068 if (!getLangOpts().OpenACC)
1069 return;
1070
1071 if (!LoopInfo.TopLevelLoopSeen)
1072 return;
1073
1074 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
1075 Diag(DoLoc, diag::err_acc_invalid_in_loop)
1076 << /*do loop*/ 2 << CollapseInfo.DirectiveKind
1078 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
1079 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1080 diag::note_acc_active_clause_here)
1082
1083 // Remove the value so that we don't get cascading errors in the body. The
1084 // caller RAII object will restore this.
1085 CollapseInfo.CurCollapseCount = std::nullopt;
1086 }
1087
1088 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
1089 Diag(DoLoc, diag::err_acc_invalid_in_loop)
1090 << /*do loop*/ 2 << TileInfo.DirectiveKind << OpenACCClauseKind::Tile;
1091 assert(TileInfo.ActiveTile && "tile count without object?");
1092 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
1094
1095 // Remove the value so that we don't get cascading errors in the body. The
1096 // caller RAII object will restore this.
1097 TileInfo.CurTileCount = std::nullopt;
1098 }
1099}
1100
1101void SemaOpenACC::ForStmtBeginHelper(SourceLocation ForLoc,
1102 ForStmtBeginChecker &C) {
1103 assert(getLangOpts().OpenACC && "Check enabled when not OpenACC?");
1104
1105 // Enable the while/do-while checking.
1106 LoopInfo.TopLevelLoopSeen = true;
1107
1108 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
1109 // Check the format of this loop if it is affected by the collapse.
1110 C.check();
1111
1112 // OpenACC 3.3 2.9.1:
1113 // Each associated loop, except the innermost, must contain exactly one loop
1114 // or loop nest.
1115 // This checks for more than 1 loop at the current level, the
1116 // 'depth'-satisifed checking manages the 'not zero' case.
1117 if (LoopInfo.CurLevelHasLoopAlready) {
1118 Diag(ForLoc, diag::err_acc_clause_multiple_loops)
1119 << CollapseInfo.DirectiveKind << OpenACCClauseKind::Collapse;
1120 assert(CollapseInfo.ActiveCollapse && "No collapse object?");
1121 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1122 diag::note_acc_active_clause_here)
1124 } else {
1125 --(*CollapseInfo.CurCollapseCount);
1126
1127 // Once we've hit zero here, we know we have deep enough 'for' loops to
1128 // get to the bottom.
1129 if (*CollapseInfo.CurCollapseCount == 0)
1130 CollapseInfo.CollapseDepthSatisfied = true;
1131 }
1132 }
1133
1134 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
1135 // Check the format of this loop if it is affected by the tile.
1136 C.check();
1137
1138 if (LoopInfo.CurLevelHasLoopAlready) {
1139 Diag(ForLoc, diag::err_acc_clause_multiple_loops)
1140 << TileInfo.DirectiveKind << OpenACCClauseKind::Tile;
1141 assert(TileInfo.ActiveTile && "No tile object?");
1142 Diag(TileInfo.ActiveTile->getBeginLoc(),
1143 diag::note_acc_active_clause_here)
1145 } else {
1146 TileInfo.CurTileCount = *TileInfo.CurTileCount - 1;
1147 // Once we've hit zero here, we know we have deep enough 'for' loops to
1148 // get to the bottom.
1149 if (*TileInfo.CurTileCount == 0)
1150 TileInfo.TileDepthSatisfied = true;
1151 }
1152 }
1153
1154 // Set this to 'false' for the body of this loop, so that the next level
1155 // checks independently.
1156 LoopInfo.CurLevelHasLoopAlready = false;
1157}
1158
1159namespace {
1160bool isValidLoopVariableType(QualType LoopVarTy) {
1161 // Just skip if it is dependent, it could be any of the below.
1162 if (LoopVarTy->isDependentType())
1163 return true;
1164
1165 // The loop variable must be of integer,
1166 if (LoopVarTy->isIntegerType())
1167 return true;
1168
1169 // C/C++ pointer,
1170 if (LoopVarTy->isPointerType())
1171 return true;
1172
1173 // or C++ random-access iterator type.
1174 if (const auto *RD = LoopVarTy->getAsCXXRecordDecl()) {
1175 // Note: Only do CXXRecordDecl because RecordDecl can't be a random access
1176 // iterator type!
1177
1178 // We could either do a lot of work to see if this matches
1179 // random-access-iterator, but it seems that just checking that the
1180 // 'iterator_category' typedef is more than sufficient. If programmers are
1181 // willing to lie about this, we can let them.
1182
1183 for (const auto *TD :
1184 llvm::make_filter_range(RD->decls(), llvm::IsaPred<TypedefNameDecl>)) {
1185 const auto *TDND = cast<TypedefNameDecl>(TD)->getCanonicalDecl();
1186
1187 if (TDND->getName() != "iterator_category")
1188 continue;
1189
1190 // If there is no type for this decl, return false.
1191 if (TDND->getUnderlyingType().isNull())
1192 return false;
1193
1194 const CXXRecordDecl *ItrCategoryDecl =
1195 TDND->getUnderlyingType()->getAsCXXRecordDecl();
1196
1197 // If the category isn't a record decl, it isn't the tag type.
1198 if (!ItrCategoryDecl)
1199 return false;
1200
1201 auto IsRandomAccessIteratorTag = [](const CXXRecordDecl *RD) {
1202 if (RD->getName() != "random_access_iterator_tag")
1203 return false;
1204 // Checks just for std::random_access_iterator_tag.
1206 };
1207
1208 if (IsRandomAccessIteratorTag(ItrCategoryDecl))
1209 return true;
1210
1211 // We can also support tag-types inherited from the
1212 // random_access_iterator_tag.
1213 for (CXXBaseSpecifier BS : ItrCategoryDecl->bases())
1214 if (IsRandomAccessIteratorTag(BS.getType()->getAsCXXRecordDecl()))
1215 return true;
1216
1217 return false;
1218 }
1219 }
1220
1221 return false;
1222}
1223const ValueDecl *getDeclFromExpr(const Expr *E) {
1224 E = E->IgnoreParenImpCasts();
1225 if (const auto *FE = dyn_cast<FullExpr>(E))
1226 E = FE->getSubExpr();
1227
1228 E = E->IgnoreParenImpCasts();
1229
1230 if (!E)
1231 return nullptr;
1232 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
1233 return dyn_cast<ValueDecl>(DRE->getDecl());
1234
1235 if (const auto *ME = dyn_cast<MemberExpr>(E))
1236 if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
1237 return ME->getMemberDecl();
1238
1239 return nullptr;
1240}
1241} // namespace
1242
1243void SemaOpenACC::ForStmtBeginChecker::checkRangeFor() {
1244 const RangeForInfo &RFI = std::get<RangeForInfo>(Info);
1245 // If this hasn't changed since last instantiated we're done.
1246 if (RFI.Uninstantiated == RFI.CurrentVersion)
1247 return;
1248
1249 const DeclStmt *UninstRangeStmt =
1250 IsInstantiation ? RFI.Uninstantiated->getBeginStmt() : nullptr;
1251 const DeclStmt *RangeStmt = RFI.CurrentVersion->getBeginStmt();
1252
1253 // If this isn't the first time we've checked this loop, suppress any cases
1254 // where we previously diagnosed.
1255 if (UninstRangeStmt) {
1256 const ValueDecl *InitVar =
1257 cast<ValueDecl>(UninstRangeStmt->getSingleDecl());
1258 QualType VarType = InitVar->getType().getNonReferenceType();
1259
1260 if (!isValidLoopVariableType(VarType))
1261 return;
1262 }
1263
1264 // In some dependent contexts, the autogenerated range statement doesn't get
1265 // included until instantiation, so skip for now.
1266 if (RangeStmt) {
1267 const ValueDecl *InitVar = cast<ValueDecl>(RangeStmt->getSingleDecl());
1268 QualType VarType = InitVar->getType().getNonReferenceType();
1269
1270 if (!isValidLoopVariableType(VarType)) {
1271 SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type)
1272 << SemaRef.LoopWithoutSeqInfo.Kind << VarType;
1273 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1274 diag::note_acc_construct_here)
1275 << SemaRef.LoopWithoutSeqInfo.Kind;
1276 return;
1277 }
1278 }
1279}
1280bool SemaOpenACC::ForStmtBeginChecker::checkForInit(const Stmt *InitStmt,
1281 const ValueDecl *&InitVar,
1282 bool Diag) {
1283 // Init statement is required.
1284 if (!InitStmt) {
1285 if (Diag) {
1286 SemaRef.Diag(ForLoc, diag::err_acc_loop_variable)
1287 << SemaRef.LoopWithoutSeqInfo.Kind;
1288 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1289 diag::note_acc_construct_here)
1290 << SemaRef.LoopWithoutSeqInfo.Kind;
1291 }
1292 return true;
1293 }
1294 auto DiagLoopVar = [this, Diag, InitStmt]() {
1295 if (Diag) {
1296 SemaRef.Diag(InitStmt->getBeginLoc(), diag::err_acc_loop_variable)
1297 << SemaRef.LoopWithoutSeqInfo.Kind;
1298 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1299 diag::note_acc_construct_here)
1300 << SemaRef.LoopWithoutSeqInfo.Kind;
1301 }
1302 return true;
1303 };
1304
1305 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(InitStmt))
1306 InitStmt = ExprTemp->getSubExpr();
1307 if (const auto *E = dyn_cast<Expr>(InitStmt))
1308 InitStmt = E->IgnoreParenImpCasts();
1309
1310 InitVar = nullptr;
1311 if (const auto *BO = dyn_cast<BinaryOperator>(InitStmt)) {
1312 // Allow assignment operator here.
1313
1314 if (!BO->isAssignmentOp())
1315 return DiagLoopVar();
1316
1317 const Expr *LHS = BO->getLHS()->IgnoreParenImpCasts();
1318 if (const auto *DRE = dyn_cast<DeclRefExpr>(LHS))
1319 InitVar = DRE->getDecl();
1320 } else if (const auto *DS = dyn_cast<DeclStmt>(InitStmt)) {
1321 // Allow T t = <whatever>
1322 if (!DS->isSingleDecl())
1323 return DiagLoopVar();
1324 InitVar = dyn_cast<ValueDecl>(DS->getSingleDecl());
1325
1326 // Ensure we have an initializer, unless this is a record/dependent type.
1327 if (InitVar) {
1328 if (!isa<VarDecl>(InitVar))
1329 return DiagLoopVar();
1330
1331 if (!InitVar->getType()->isRecordType() &&
1332 !InitVar->getType()->isDependentType() &&
1333 !cast<VarDecl>(InitVar)->hasInit())
1334 return DiagLoopVar();
1335 }
1336 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(InitStmt)) {
1337 // Allow assignment operator call.
1338 if (CE->getOperator() != OO_Equal)
1339 return DiagLoopVar();
1340
1341 const Expr *LHS = CE->getArg(0)->IgnoreParenImpCasts();
1342 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
1343 InitVar = DRE->getDecl();
1344 } else if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
1345 if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
1346 InitVar = ME->getMemberDecl();
1347 }
1348 }
1349
1350 // If after all of that, we haven't found a variable, give up.
1351 if (!InitVar)
1352 return DiagLoopVar();
1353
1354 InitVar = cast<ValueDecl>(InitVar->getCanonicalDecl());
1355 QualType VarType = InitVar->getType().getNonReferenceType();
1356
1357 // Since we have one, all we need to do is ensure it is the right type.
1358 if (!isValidLoopVariableType(VarType)) {
1359 if (Diag) {
1360 SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type)
1361 << SemaRef.LoopWithoutSeqInfo.Kind << VarType;
1362 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1363 diag::note_acc_construct_here)
1364 << SemaRef.LoopWithoutSeqInfo.Kind;
1365 }
1366 return true;
1367 }
1368
1369 return false;
1370}
1371
1372bool SemaOpenACC::ForStmtBeginChecker::checkForCond(const Stmt *CondStmt,
1373 const ValueDecl *InitVar,
1374 bool Diag) {
1375 // A condition statement is required.
1376 if (!CondStmt) {
1377 if (Diag) {
1378 SemaRef.Diag(ForLoc, diag::err_acc_loop_terminating_condition)
1379 << SemaRef.LoopWithoutSeqInfo.Kind;
1380 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1381 diag::note_acc_construct_here)
1382 << SemaRef.LoopWithoutSeqInfo.Kind;
1383 }
1384
1385 return true;
1386 }
1387 auto DiagCondVar = [this, Diag, CondStmt] {
1388 if (Diag) {
1389 SemaRef.Diag(CondStmt->getBeginLoc(),
1390 diag::err_acc_loop_terminating_condition)
1391 << SemaRef.LoopWithoutSeqInfo.Kind;
1392 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1393 diag::note_acc_construct_here)
1394 << SemaRef.LoopWithoutSeqInfo.Kind;
1395 }
1396 return true;
1397 };
1398
1399 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(CondStmt))
1400 CondStmt = ExprTemp->getSubExpr();
1401 if (const auto *E = dyn_cast<Expr>(CondStmt))
1402 CondStmt = E->IgnoreParenImpCasts();
1403
1404 const ValueDecl *CondVar = nullptr;
1405 if (const auto *BO = dyn_cast<BinaryOperator>(CondStmt)) {
1406 switch (BO->getOpcode()) {
1407 default:
1408 return DiagCondVar();
1409 case BO_EQ:
1410 case BO_LT:
1411 case BO_GT:
1412 case BO_NE:
1413 case BO_LE:
1414 case BO_GE:
1415 break;
1416 }
1417
1418 // Assign the condition-var to the LHS. If it either comes back null, or
1419 // the LHS doesn't match the InitVar, assign it to the RHS so that 5 < N is
1420 // allowed.
1421 CondVar = getDeclFromExpr(BO->getLHS());
1422 if (!CondVar ||
1423 (InitVar && CondVar->getCanonicalDecl() != InitVar->getCanonicalDecl()))
1424 CondVar = getDeclFromExpr(BO->getRHS());
1425
1426 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(CondStmt)) {
1427 // Any of the comparison ops should be ok here, but we don't know how to
1428 // handle spaceship, so disallow for now.
1429 if (!CE->isComparisonOp() || CE->getOperator() == OO_Spaceship)
1430 return DiagCondVar();
1431
1432 // Same logic here: Assign it to the LHS, unless the LHS comes back null or
1433 // not equal to the init var.
1434 CondVar = getDeclFromExpr(CE->getArg(0));
1435 if (!CondVar ||
1436 (InitVar &&
1437 CondVar->getCanonicalDecl() != InitVar->getCanonicalDecl() &&
1438 CE->getNumArgs() > 1))
1439 CondVar = getDeclFromExpr(CE->getArg(1));
1440 } else {
1441 return DiagCondVar();
1442 }
1443
1444 if (!CondVar)
1445 return DiagCondVar();
1446
1447 // Don't consider this an error unless the init variable was properly set,
1448 // else check to make sure they are the same variable.
1449 if (InitVar && CondVar->getCanonicalDecl() != InitVar->getCanonicalDecl())
1450 return DiagCondVar();
1451
1452 return false;
1453}
1454
1455namespace {
1456// Helper to check the RHS of an assignment during for's step. We can allow
1457// InitVar = InitVar + N, InitVar = N + InitVar, and Initvar = Initvar - N,
1458// where N is an integer.
1459bool isValidForIncRHSAssign(const ValueDecl *InitVar, const Expr *RHS) {
1460
1461 auto isValid = [](const ValueDecl *InitVar, const Expr *InnerLHS,
1462 const Expr *InnerRHS, bool IsAddition) {
1463 // ONE of the sides has to be an integer type.
1464 if (!InnerLHS->getType()->isIntegerType() &&
1465 !InnerRHS->getType()->isIntegerType())
1466 return false;
1467
1468 // If the init var is already an error, don't bother trying to check for
1469 // it.
1470 if (!InitVar)
1471 return true;
1472
1473 const ValueDecl *LHSDecl = getDeclFromExpr(InnerLHS);
1474 const ValueDecl *RHSDecl = getDeclFromExpr(InnerRHS);
1475 // If we can't get a declaration, this is probably an error, so give up.
1476 if (!LHSDecl || !RHSDecl)
1477 return true;
1478
1479 // If the LHS is the InitVar, the other must be int, so this is valid.
1480 if (LHSDecl->getCanonicalDecl() ==
1481 InitVar->getCanonicalDecl())
1482 return true;
1483
1484 // Subtraction doesn't allow the RHS to be init var, so this is invalid.
1485 if (!IsAddition)
1486 return false;
1487
1488 return RHSDecl->getCanonicalDecl() ==
1489 InitVar->getCanonicalDecl();
1490 };
1491
1492 if (const auto *BO = dyn_cast<BinaryOperator>(RHS)) {
1493 BinaryOperatorKind OpC = BO->getOpcode();
1494 if (OpC != BO_Add && OpC != BO_Sub)
1495 return false;
1496 return isValid(InitVar, BO->getLHS(), BO->getRHS(), OpC == BO_Add);
1497 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
1498 OverloadedOperatorKind Op = CE->getOperator();
1499 if (Op != OO_Plus && Op != OO_Minus)
1500 return false;
1501 return isValid(InitVar, CE->getArg(0), CE->getArg(1), Op == OO_Plus);
1502 }
1503
1504 return false;
1505}
1506} // namespace
1507
1508bool SemaOpenACC::ForStmtBeginChecker::checkForInc(const Stmt *IncStmt,
1509 const ValueDecl *InitVar,
1510 bool Diag) {
1511 if (!IncStmt) {
1512 if (Diag) {
1513 SemaRef.Diag(ForLoc, diag::err_acc_loop_not_monotonic)
1514 << SemaRef.LoopWithoutSeqInfo.Kind;
1515 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1516 diag::note_acc_construct_here)
1517 << SemaRef.LoopWithoutSeqInfo.Kind;
1518 }
1519 return true;
1520 }
1521 auto DiagIncVar = [this, Diag, IncStmt] {
1522 if (Diag) {
1523 SemaRef.Diag(IncStmt->getBeginLoc(), diag::err_acc_loop_not_monotonic)
1524 << SemaRef.LoopWithoutSeqInfo.Kind;
1525 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1526 diag::note_acc_construct_here)
1527 << SemaRef.LoopWithoutSeqInfo.Kind;
1528 }
1529 return true;
1530 };
1531
1532 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(IncStmt))
1533 IncStmt = ExprTemp->getSubExpr();
1534 if (const auto *E = dyn_cast<Expr>(IncStmt))
1535 IncStmt = E->IgnoreParenImpCasts();
1536
1537 const ValueDecl *IncVar = nullptr;
1538 // Here we enforce the monotonically increase/decrease:
1539 if (const auto *UO = dyn_cast<UnaryOperator>(IncStmt)) {
1540 // Allow increment/decrement ops.
1541 if (!UO->isIncrementDecrementOp())
1542 return DiagIncVar();
1543 IncVar = getDeclFromExpr(UO->getSubExpr());
1544 } else if (const auto *BO = dyn_cast<BinaryOperator>(IncStmt)) {
1545 switch (BO->getOpcode()) {
1546 default:
1547 return DiagIncVar();
1548 case BO_AddAssign:
1549 case BO_SubAssign:
1550 break;
1551 case BO_Assign:
1552 // For assignment we also allow InitVar = InitVar + N, InitVar = N +
1553 // InitVar, and InitVar = InitVar - N; BUT only if 'N' is integral.
1554 if (!isValidForIncRHSAssign(InitVar, BO->getRHS()))
1555 return DiagIncVar();
1556 break;
1557 }
1558 IncVar = getDeclFromExpr(BO->getLHS());
1559 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(IncStmt)) {
1560 switch (CE->getOperator()) {
1561 default:
1562 return DiagIncVar();
1563 case OO_PlusPlus:
1564 case OO_MinusMinus:
1565 case OO_PlusEqual:
1566 case OO_MinusEqual:
1567 break;
1568 case OO_Equal:
1569 // For assignment we also allow InitVar = InitVar + N, InitVar = N +
1570 // InitVar, and InitVar = InitVar - N; BUT only if 'N' is integral.
1571 if (!isValidForIncRHSAssign(InitVar, CE->getArg(1)))
1572 return DiagIncVar();
1573 break;
1574 }
1575
1576 IncVar = getDeclFromExpr(CE->getArg(0));
1577 } else {
1578 return DiagIncVar();
1579 }
1580
1581 if (!IncVar)
1582 return DiagIncVar();
1583
1584 // InitVar shouldn't be null unless there was an error, so don't diagnose if
1585 // that is the case. Else we should ensure that it refers to the loop
1586 // value.
1587 if (InitVar && IncVar->getCanonicalDecl() != InitVar->getCanonicalDecl())
1588 return DiagIncVar();
1589
1590 return false;
1591}
1592
1593void SemaOpenACC::ForStmtBeginChecker::checkFor() {
1594 const CheckForInfo &CFI = std::get<CheckForInfo>(Info);
1595
1596 if (!IsInstantiation) {
1597 // If this isn't an instantiation, we can just check all of these and
1598 // diagnose.
1599 const ValueDecl *CurInitVar = nullptr;
1600 checkForInit(CFI.Current.Init, CurInitVar, /*Diag=*/true);
1601 checkForCond(CFI.Current.Condition, CurInitVar, /*Diag=*/true);
1602 checkForInc(CFI.Current.Increment, CurInitVar, /*DIag=*/true);
1603 } else {
1604 const ValueDecl *UninstInitVar = nullptr;
1605 // Checking the 'init' section first. We have to always run both versions,
1606 // at minimum with the 'diag' off, so that we can ensure we get the correct
1607 // instantiation var for checking by later ones.
1608 bool UninstInitFailed =
1609 checkForInit(CFI.Uninst.Init, UninstInitVar, /*Diag=*/false);
1610
1611 // VarDecls are always rebuild because they are dependent, so we can do a
1612 // little work to suppress some of the double checking based on whether the
1613 // type is instantiation dependent. This is imperfect, but will get us most
1614 // cases suppressed. Currently this only handles the 'T t =' case.
1615 auto InitChanged = [=]() {
1616 if (CFI.Uninst.Init == CFI.Current.Init)
1617 return false;
1618
1619 QualType OldVDTy;
1620 QualType NewVDTy;
1621
1622 if (const auto *DS = dyn_cast<DeclStmt>(CFI.Uninst.Init))
1623 if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1624 DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
1625 OldVDTy = VD->getType();
1626 if (const auto *DS = dyn_cast<DeclStmt>(CFI.Current.Init))
1627 if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1628 DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
1629 NewVDTy = VD->getType();
1630
1631 if (OldVDTy.isNull() || NewVDTy.isNull())
1632 return true;
1633
1634 return OldVDTy->isInstantiationDependentType() !=
1636 };
1637
1638 // Only diagnose the new 'init' if the previous version didn't fail, AND the
1639 // current init changed meaningfully.
1640 bool ShouldDiagNewInit = !UninstInitFailed && InitChanged();
1641 const ValueDecl *CurInitVar = nullptr;
1642 checkForInit(CFI.Current.Init, CurInitVar, /*Diag=*/ShouldDiagNewInit);
1643
1644 // Check the condition and increment only if the previous version passed,
1645 // and this changed.
1646 if (CFI.Uninst.Condition != CFI.Current.Condition &&
1647 !checkForCond(CFI.Uninst.Condition, UninstInitVar, /*Diag=*/false))
1648 checkForCond(CFI.Current.Condition, CurInitVar, /*Diag=*/true);
1649 if (CFI.Uninst.Increment != CFI.Current.Increment &&
1650 !checkForInc(CFI.Uninst.Increment, UninstInitVar, /*Diag=*/false))
1651 checkForInc(CFI.Current.Increment, CurInitVar, /*Diag=*/true);
1652 }
1653}
1654
1655void SemaOpenACC::ForStmtBeginChecker::check() {
1656 // If this isn't an active loop without a seq, immediately return, nothing to
1657 // check.
1658 if (SemaRef.LoopWithoutSeqInfo.Kind == OpenACCDirectiveKind::Invalid)
1659 return;
1660
1661 // If we've already checked, because this is a 'top level' one (and asking
1662 // again because 'tile' and 'collapse' might apply), just return, nothing to
1663 // do here.
1664 if (AlreadyChecked)
1665 return;
1666 AlreadyChecked = true;
1667
1668 // OpenACC3.3 2.1:
1669 // A loop associated with a loop construct that does not have a seq clause
1670 // must be written to meet all the following conditions:
1671 // - The loop variable must be of integer, C/C++ pointer, or C++ random-access
1672 // iterator type.
1673 // - The loop variable must monotonically increase or decrease in the
1674 // direction of its termination condition.
1675 // - The loop trip count must be computable in constant time when entering the
1676 // loop construct.
1677 //
1678 // For a C++ range-based for loop, the loop variable
1679 // identified by the above conditions is the internal iterator, such as a
1680 // pointer, that the compiler generates to iterate the range. it is not the
1681 // variable declared by the for loop.
1682
1683 if (std::holds_alternative<RangeForInfo>(Info))
1684 return checkRangeFor();
1685
1686 return checkFor();
1687}
1688
1690 const Stmt *First, const Stmt *OldSecond,
1691 const Stmt *Second, const Stmt *OldThird,
1692 const Stmt *Third) {
1693 if (!getLangOpts().OpenACC)
1694 return;
1695
1696 ForStmtBeginChecker FSBC{*this, ForLoc, OldFirst, OldSecond,
1697 OldThird, First, Second, Third};
1698 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1699 // as a part of the helper if a tile/collapse applies.
1700 if (!LoopInfo.TopLevelLoopSeen) {
1701 FSBC.check();
1702 }
1703
1704 ForStmtBeginHelper(ForLoc, FSBC);
1705}
1706
1708 const Stmt *Second, const Stmt *Third) {
1709 if (!getLangOpts().OpenACC)
1710 return;
1711
1712 ForStmtBeginChecker FSBC{*this, ForLoc, First, Second, Third};
1713
1714 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1715 // as a part of the helper if a tile/collapse applies.
1716 if (!LoopInfo.TopLevelLoopSeen)
1717 FSBC.check();
1718
1719 ForStmtBeginHelper(ForLoc, FSBC);
1720}
1721
1723 const Stmt *OldRangeFor,
1724 const Stmt *RangeFor) {
1725 if (!getLangOpts().OpenACC || OldRangeFor == nullptr || RangeFor == nullptr)
1726 return;
1727
1728 ForStmtBeginChecker FSBC{*this, ForLoc,
1729 cast_if_present<CXXForRangeStmt>(OldRangeFor),
1730 cast_if_present<CXXForRangeStmt>(RangeFor)};
1731 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1732 // as a part of the helper if a tile/collapse applies.
1733 if (!LoopInfo.TopLevelLoopSeen) {
1734 FSBC.check();
1735 }
1736 ForStmtBeginHelper(ForLoc, FSBC);
1737}
1738
1740 const Stmt *RangeFor) {
1741 if (!getLangOpts().OpenACC || RangeFor == nullptr)
1742 return;
1743
1744 ForStmtBeginChecker FSBC = {*this, ForLoc,
1745 cast_if_present<CXXForRangeStmt>(RangeFor)};
1746
1747 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1748 // as a part of the helper if a tile/collapse applies.
1749 if (!LoopInfo.TopLevelLoopSeen)
1750 FSBC.check();
1751
1752 ForStmtBeginHelper(ForLoc, FSBC);
1753}
1754
1755namespace {
1756SourceLocation FindInterveningCodeInLoop(const Stmt *CurStmt) {
1757 // We should diagnose on anything except `CompoundStmt`, `NullStmt`,
1758 // `ForStmt`, `CXXForRangeStmt`, since those are legal, and `WhileStmt` and
1759 // `DoStmt`, as those are caught as a violation elsewhere.
1760 // For `CompoundStmt` we need to search inside of it.
1761 if (!CurStmt ||
1762 isa<ForStmt, NullStmt, ForStmt, CXXForRangeStmt, WhileStmt, DoStmt>(
1763 CurStmt))
1764 return SourceLocation{};
1765
1766 // Any other construct is an error anyway, so it has already been diagnosed.
1767 if (isa<OpenACCConstructStmt>(CurStmt))
1768 return SourceLocation{};
1769
1770 // Search inside the compound statement, this allows for arbitrary nesting
1771 // of compound statements, as long as there isn't any code inside.
1772 if (const auto *CS = dyn_cast<CompoundStmt>(CurStmt)) {
1773 for (const auto *ChildStmt : CS->children()) {
1774 SourceLocation ChildStmtLoc = FindInterveningCodeInLoop(ChildStmt);
1775 if (ChildStmtLoc.isValid())
1776 return ChildStmtLoc;
1777 }
1778 // Empty/not invalid compound statements are legal.
1779 return SourceLocation{};
1780 }
1781 return CurStmt->getBeginLoc();
1782}
1783} // namespace
1784
1786 if (!getLangOpts().OpenACC)
1787 return;
1788
1789 // Set this to 'true' so if we find another one at this level we can diagnose.
1790 LoopInfo.CurLevelHasLoopAlready = true;
1791
1792 if (!Body.isUsable())
1793 return;
1794
1795 bool IsActiveCollapse = CollapseInfo.CurCollapseCount &&
1796 *CollapseInfo.CurCollapseCount > 0 &&
1797 !CollapseInfo.ActiveCollapse->hasForce();
1798 bool IsActiveTile = TileInfo.CurTileCount && *TileInfo.CurTileCount > 0;
1799
1800 if (IsActiveCollapse || IsActiveTile) {
1801 SourceLocation OtherStmtLoc = FindInterveningCodeInLoop(Body.get());
1802
1803 if (OtherStmtLoc.isValid() && IsActiveCollapse) {
1804 Diag(OtherStmtLoc, diag::err_acc_intervening_code)
1805 << OpenACCClauseKind::Collapse << CollapseInfo.DirectiveKind;
1806 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1807 diag::note_acc_active_clause_here)
1809 }
1810
1811 if (OtherStmtLoc.isValid() && IsActiveTile) {
1812 Diag(OtherStmtLoc, diag::err_acc_intervening_code)
1813 << OpenACCClauseKind::Tile << TileInfo.DirectiveKind;
1814 Diag(TileInfo.ActiveTile->getBeginLoc(),
1815 diag::note_acc_active_clause_here)
1817 }
1818 }
1819}
1820
1821namespace {
1822// Helper that should mirror ActOnRoutineName to get the FunctionDecl out for
1823// magic-static checking.
1824FunctionDecl *getFunctionFromRoutineName(Expr *RoutineName) {
1825 if (!RoutineName)
1826 return nullptr;
1827 RoutineName = RoutineName->IgnoreParenImpCasts();
1828 if (isa<RecoveryExpr>(RoutineName)) {
1829 // There is nothing we can do here, this isn't a function we can count on.
1830 return nullptr;
1831 } else if (isa<DependentScopeDeclRefExpr, CXXDependentScopeMemberExpr>(
1832 RoutineName)) {
1833 // The lookup is dependent, so we'll have to figure this out later.
1834 return nullptr;
1835 } else if (auto *DRE = dyn_cast<DeclRefExpr>(RoutineName)) {
1836 ValueDecl *VD = DRE->getDecl();
1837
1838 if (auto *FD = dyn_cast<FunctionDecl>(VD))
1839 return FD;
1840
1841 // Allow lambdas.
1842 if (auto *VarD = dyn_cast<VarDecl>(VD)) {
1843 QualType VarDTy = VarD->getType();
1844 if (!VarDTy.isNull()) {
1845 if (auto *RD = VarDTy->getAsCXXRecordDecl()) {
1846 if (RD->isGenericLambda())
1847 return nullptr;
1848 if (RD->isLambda())
1849 return RD->getLambdaCallOperator();
1850 } else if (VarDTy->isDependentType()) {
1851 // We don't really know what this is going to be.
1852 return nullptr;
1853 }
1854 }
1855 return nullptr;
1856 } else if (isa<OverloadExpr>(RoutineName)) {
1857 return nullptr;
1858 }
1859 }
1860 return nullptr;
1861}
1862} // namespace
1863
1865 assert(RoutineName && "Routine name cannot be null here");
1866 RoutineName = RoutineName->IgnoreParenImpCasts();
1867
1868 if (isa<RecoveryExpr>(RoutineName)) {
1869 // This has already been diagnosed, so we can skip it.
1870 return ExprError();
1871 } else if (isa<DependentScopeDeclRefExpr, CXXDependentScopeMemberExpr>(
1872 RoutineName)) {
1873 // These are dependent and we can't really check them, so delay until
1874 // instantiation.
1875 return RoutineName;
1876 } else if (const auto *DRE = dyn_cast<DeclRefExpr>(RoutineName)) {
1877 const ValueDecl *VD = DRE->getDecl();
1878
1879 if (isa<FunctionDecl>(VD))
1880 return RoutineName;
1881
1882 // Allow lambdas.
1883 if (const auto *VarD = dyn_cast<VarDecl>(VD)) {
1884 QualType VarDTy = VarD->getType();
1885 if (!VarDTy.isNull()) {
1886 if (const auto *RD = VarDTy->getAsCXXRecordDecl()) {
1887 if (RD->isGenericLambda()) {
1888 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_overload_set)
1889 << RoutineName;
1890 return ExprError();
1891 }
1892 if (RD->isLambda())
1893 return RoutineName;
1894 } else if (VarDTy->isDependentType()) {
1895 // If this is a dependent variable, it might be a lambda. So we just
1896 // accept this and catch it next time.
1897 return RoutineName;
1898 }
1899 }
1900 }
1901
1902 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_not_func)
1903 << RoutineName;
1904 return ExprError();
1905 } else if (isa<OverloadExpr>(RoutineName)) {
1906 // This happens in function templates, even when the template arguments are
1907 // fully specified. We could possibly do some sort of matching to make sure
1908 // that this is looked up/deduced, but GCC does not do this, so there
1909 // doesn't seem to be a good reason for us to do it either.
1910 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_overload_set)
1911 << RoutineName;
1912 return ExprError();
1913 }
1914
1915 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_not_func)
1916 << RoutineName;
1917 return ExprError();
1918}
1920 if (!getLangOpts().OpenACC || VD->isInvalidDecl() || !VD->isStaticLocal())
1921 return;
1922
1923 // This cast should be safe, since a static-local can only happen in a
1924 // function declaration. However, in error cases (or perhaps ObjC/C++?), this
1925 // could possibly be something like a 'block' decl, so if this is NOT a
1926 // function decl, just give up.
1927 auto *ContextDecl = dyn_cast<FunctionDecl>(getCurContext());
1928
1929 if (!ContextDecl)
1930 return;
1931
1932 // OpenACC 3.3 2.15:
1933 // In C and C++, function static variables are not supported in functions to
1934 // which a routine directive applies.
1935 for (const auto *A : ContextDecl->attrs()) {
1936 if (isa<OpenACCRoutineDeclAttr, OpenACCRoutineAnnotAttr>(A)) {
1937 Diag(VD->getBeginLoc(), diag::err_acc_magic_static_in_routine);
1938 Diag(A->getLocation(), diag::note_acc_construct_here)
1940 return;
1941 }
1942 }
1943
1944 MagicStaticLocs.insert({ContextDecl->getCanonicalDecl(), VD->getBeginLoc()});
1945}
1946void SemaOpenACC::CheckLastRoutineDeclNameConflict(const NamedDecl *ND) {
1947 // OpenACC 3.3 A.3.4
1948 // When a procedure with that name is in scope and it is not the same
1949 // procedure as the immediately following procedure declaration or
1950 // definition, the resolution of the name can be confusing. Implementations
1951 // should then issue a compile-time warning diagnostic even though the
1952 // application is conforming.
1953
1954 // If we haven't created one, also can't diagnose.
1955 if (!LastRoutineDecl)
1956 return;
1957
1958 // If the currently created function doesn't have a name, we can't diagnose on
1959 // a match.
1960 if (!ND->getDeclName().isIdentifier())
1961 return;
1962
1963 // If the two are in different decl contexts, it doesn't make sense to
1964 // diagnose.
1965 if (LastRoutineDecl->getDeclContext() != ND->getLexicalDeclContext())
1966 return;
1967
1968 // If we don't have a referenced thing yet, we can't diagnose.
1969 FunctionDecl *RoutineTarget =
1970 getFunctionFromRoutineName(LastRoutineDecl->getFunctionReference());
1971 if (!RoutineTarget)
1972 return;
1973
1974 // If the Routine target doesn't have a name, we can't diagnose.
1975 if (!RoutineTarget->getDeclName().isIdentifier())
1976 return;
1977
1978 // Of course don't diagnose if the names don't match.
1979 if (ND->getName() != RoutineTarget->getName())
1980 return;
1981
1983 long LastLine =
1985
1986 // Do some line-number math to make sure they are within a line of eachother.
1987 // Comments or newlines can be inserted to clarify intent.
1988 if (NDLine - LastLine > 1)
1989 return;
1990
1991 // Don't warn if it actually DOES apply to this function via redecls.
1992 if (ND->getCanonicalDecl() == RoutineTarget->getCanonicalDecl())
1993 return;
1994
1995 Diag(LastRoutineDecl->getFunctionReference()->getBeginLoc(),
1996 diag::warn_acc_confusing_routine_name);
1997 Diag(RoutineTarget->getBeginLoc(), diag::note_previous_decl) << ND;
1998}
1999
2001 if (!VD || !getLangOpts().OpenACC || InitType.isNull())
2002 return;
2003
2004 // To avoid double-diagnostic, just diagnose this during instantiation. We'll
2005 // get 1 warning per instantiation, but this permits us to be more sensible
2006 // for cases where the lookup is confusing.
2008 return;
2009
2010 const auto *RD = InitType->getAsCXXRecordDecl();
2011 // If this isn't a lambda, no sense in diagnosing.
2012 if (!RD || !RD->isLambda())
2013 return;
2014
2015 CheckLastRoutineDeclNameConflict(VD);
2016}
2017
2019 if (!FD || !getLangOpts().OpenACC)
2020 return;
2021 CheckLastRoutineDeclNameConflict(FD);
2022}
2023
2027
2028 // Declaration directives an appear in a statement location, so call into that
2029 // function here.
2031 return ActOnStartDeclDirective(K, StartLoc, Clauses);
2032
2035
2036 // OpenACC 3.3 2.9.1:
2037 // Intervening code must not contain other OpenACC directives or calls to API
2038 // routines.
2039 //
2040 // ALL constructs are ill-formed if there is an active 'collapse'
2041 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
2042 Diag(StartLoc, diag::err_acc_invalid_in_loop)
2043 << /*OpenACC Construct*/ 0 << CollapseInfo.DirectiveKind
2045 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
2046 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
2047 diag::note_acc_active_clause_here)
2049 }
2050 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
2051 Diag(StartLoc, diag::err_acc_invalid_in_loop)
2052 << /*OpenACC Construct*/ 0 << TileInfo.DirectiveKind
2054 assert(TileInfo.ActiveTile && "Tile count without object?");
2055 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
2057 }
2058
2059 if (DiagnoseRequiredClauses(K, StartLoc, Clauses))
2060 return true;
2061 return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true);
2062}
2063
2066 SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs,
2067 OpenACCAtomicKind AtomicKind, SourceLocation RParenLoc,
2069 StmtResult AssocStmt) {
2070 switch (K) {
2072 return StmtError();
2077 getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,
2078 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2079 }
2084 getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,
2085 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2086 }
2089 getASTContext(), ActiveComputeConstructInfo.Kind, StartLoc, DirLoc,
2090 EndLoc, Clauses, AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2091 }
2094 getASTContext(), StartLoc, DirLoc, EndLoc, Clauses,
2095 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2096 }
2098 return OpenACCEnterDataConstruct::Create(getASTContext(), StartLoc, DirLoc,
2099 EndLoc, Clauses);
2100 }
2102 return OpenACCExitDataConstruct::Create(getASTContext(), StartLoc, DirLoc,
2103 EndLoc, Clauses);
2104 }
2107 getASTContext(), StartLoc, DirLoc, EndLoc, Clauses,
2108 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2109 }
2112 getASTContext(), StartLoc, DirLoc, LParenLoc, Exprs.front(), MiscLoc,
2113 Exprs.drop_front(), RParenLoc, EndLoc, Clauses);
2114 }
2116 return OpenACCInitConstruct::Create(getASTContext(), StartLoc, DirLoc,
2117 EndLoc, Clauses);
2118 }
2120 return OpenACCShutdownConstruct::Create(getASTContext(), StartLoc, DirLoc,
2121 EndLoc, Clauses);
2122 }
2124 return OpenACCSetConstruct::Create(getASTContext(), StartLoc, DirLoc,
2125 EndLoc, Clauses);
2126 }
2128 return OpenACCUpdateConstruct::Create(getASTContext(), StartLoc, DirLoc,
2129 EndLoc, Clauses);
2130 }
2133 getASTContext(), StartLoc, DirLoc, AtomicKind, EndLoc, Clauses,
2134 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2135 }
2137 assert(Clauses.empty() && "Cache doesn't allow clauses");
2138 return OpenACCCacheConstruct::Create(getASTContext(), StartLoc, DirLoc,
2139 LParenLoc, MiscLoc, Exprs, RParenLoc,
2140 EndLoc);
2141 }
2143 llvm_unreachable("routine shouldn't handled here");
2145 // Declare and routine arei declaration directives, but can be used here as
2146 // long as we wrap it in a DeclStmt. So make sure we do that here.
2147 DeclGroupRef DR = ActOnEndDeclDirective(K, StartLoc, DirLoc, LParenLoc,
2148 RParenLoc, EndLoc, Clauses);
2149
2150 return SemaRef.ActOnDeclStmt(DeclGroupPtrTy::make(DR), StartLoc, EndLoc);
2151 }
2152 }
2153 llvm_unreachable("Unhandled case in directive handling?");
2154}
2155
2157 SourceLocation DirectiveLoc, OpenACCDirectiveKind K,
2159 StmtResult AssocStmt) {
2160 switch (K) {
2161 default:
2162 llvm_unreachable("Unimplemented associated statement application");
2170 llvm_unreachable(
2171 "these don't have associated statements, so shouldn't get here");
2173 return CheckAtomicAssociatedStmt(DirectiveLoc, AtKind, AssocStmt);
2179 // There really isn't any checking here that could happen. As long as we
2180 // have a statement to associate, this should be fine.
2181 // OpenACC 3.3 Section 6:
2182 // Structured Block: in C or C++, an executable statement, possibly
2183 // compound, with a single entry at the top and a single exit at the
2184 // bottom.
2185 // FIXME: Should we reject DeclStmt's here? The standard isn't clear, and
2186 // an interpretation of it is to allow this and treat the initializer as
2187 // the 'structured block'.
2188 return AssocStmt;
2193 if (!AssocStmt.isUsable())
2194 return StmtError();
2195
2196 if (!isa<CXXForRangeStmt, ForStmt>(AssocStmt.get())) {
2197 Diag(AssocStmt.get()->getBeginLoc(), diag::err_acc_loop_not_for_loop)
2198 << K;
2199 Diag(DirectiveLoc, diag::note_acc_construct_here) << K;
2200 return StmtError();
2201 }
2202
2203 if (!CollapseInfo.CollapseDepthSatisfied || !TileInfo.TileDepthSatisfied) {
2204 if (!CollapseInfo.CollapseDepthSatisfied) {
2205 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
2207 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
2208 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
2209 diag::note_acc_active_clause_here)
2211 }
2212
2213 if (!TileInfo.TileDepthSatisfied) {
2214 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
2216 assert(TileInfo.ActiveTile && "Collapse count without object?");
2217 Diag(TileInfo.ActiveTile->getBeginLoc(),
2218 diag::note_acc_active_clause_here)
2220 }
2221 return StmtError();
2222 }
2223
2224 return AssocStmt.get();
2225 }
2226 llvm_unreachable("Invalid associated statement application");
2227}
2228
2229namespace {
2230
2231// Routine has some pretty complicated set of rules for how device_type
2232// interacts with 'gang', 'worker', 'vector', and 'seq'. Enforce part of it
2233// here.
2234bool CheckValidRoutineGangWorkerVectorSeqClauses(
2235 SemaOpenACC &SemaRef, SourceLocation DirectiveLoc,
2237 auto RequiredPred = llvm::IsaPred<OpenACCGangClause, OpenACCWorkerClause,
2239 // The clause handling has assured us that there is no duplicates. That is,
2240 // if there is 1 before a device_type, there are none after a device_type.
2241 // If not, there is at most 1 applying to each device_type.
2242
2243 // What is left to legalize is that either:
2244 // 1- there is 1 before the first device_type.
2245 // 2- there is 1 AFTER each device_type.
2246 auto *FirstDeviceType =
2247 llvm::find_if(Clauses, llvm::IsaPred<OpenACCDeviceTypeClause>);
2248
2249 // If there is 1 before the first device_type (or at all if no device_type),
2250 // we are legal.
2251 auto *ClauseItr =
2252 std::find_if(Clauses.begin(), FirstDeviceType, RequiredPred);
2253
2254 if (ClauseItr != FirstDeviceType)
2255 return false;
2256
2257 // If there IS no device_type, and no clause, diagnose.
2258 if (FirstDeviceType == Clauses.end())
2259 return SemaRef.Diag(DirectiveLoc, diag::err_acc_construct_one_clause_of)
2261 << "'gang', 'seq', 'vector', or 'worker'";
2262
2263 // Else, we have to check EACH device_type group. PrevDeviceType is the
2264 // device-type before the current group.
2265 auto *PrevDeviceType = FirstDeviceType;
2266
2267 while (PrevDeviceType != Clauses.end()) {
2268 auto *NextDeviceType =
2269 std::find_if(std::next(PrevDeviceType), Clauses.end(),
2270 llvm::IsaPred<OpenACCDeviceTypeClause>);
2271
2272 ClauseItr = std::find_if(PrevDeviceType, NextDeviceType, RequiredPred);
2273
2274 if (ClauseItr == NextDeviceType)
2275 return SemaRef.Diag((*PrevDeviceType)->getBeginLoc(),
2276 diag::err_acc_clause_routine_one_of_in_region);
2277
2278 PrevDeviceType = NextDeviceType;
2279 }
2280
2281 return false;
2282}
2283} // namespace
2284
2288 // OpenCC3.3 2.1 (line 889)
2289 // A program must not depend on the order of evaluation of expressions in
2290 // clause arguments or on any side effects of the evaluations.
2293
2294 if (DiagnoseRequiredClauses(K, StartLoc, Clauses))
2295 return true;
2297 CheckValidRoutineGangWorkerVectorSeqClauses(*this, StartLoc, Clauses))
2298 return true;
2299
2300 return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/false);
2301}
2302
2305 SourceLocation LParenLoc, SourceLocation RParenLoc, SourceLocation EndLoc,
2306 ArrayRef<OpenACCClause *> Clauses) {
2307 switch (K) {
2308 default:
2310 return DeclGroupRef{};
2312 // OpenACC3.3 2.13: At least one clause must appear on a declare directive.
2313 if (Clauses.empty()) {
2314 Diag(EndLoc, diag::err_acc_declare_required_clauses);
2315 // No reason to add this to the AST, as we would just end up trying to
2316 // instantiate this, which would double-diagnose here, which we wouldn't
2317 // want to do.
2318 return DeclGroupRef{};
2319 }
2320
2321 auto *DeclareDecl = OpenACCDeclareDecl::Create(
2322 getASTContext(), getCurContext(), StartLoc, DirLoc, EndLoc, Clauses);
2323 DeclareDecl->setAccess(AS_public);
2324 getCurContext()->addDecl(DeclareDecl);
2325 return DeclGroupRef{DeclareDecl};
2326 }
2328 llvm_unreachable("routine shouldn't be handled here");
2329 }
2330 llvm_unreachable("unhandled case in directive handling?");
2331}
2332
2333namespace {
2334// Given the decl on the next line, figure out if it is one that is acceptable
2335// to `routine`, or looks like the sort of decl we should be diagnosing against.
2336FunctionDecl *LegalizeNextParsedDecl(Decl *D) {
2337 if (!D)
2338 return nullptr;
2339
2340 // Functions are per-fact acceptable as-is.
2341 if (auto *FD = dyn_cast<FunctionDecl>(D))
2342 return FD;
2343
2344 // Function templates are functions, so attach to the templated decl.
2345 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
2346 return FTD->getTemplatedDecl();
2347
2348 if (auto *FD = dyn_cast<FieldDecl>(D)) {
2349 auto *RD =
2350 FD->getType().isNull() ? nullptr : FD->getType()->getAsCXXRecordDecl();
2351
2352 if (RD && RD->isGenericLambda())
2353 return RD->getDependentLambdaCallOperator()->getTemplatedDecl();
2354 if (RD && RD->isLambda())
2355 return RD->getLambdaCallOperator();
2356 }
2357 // VarDecl we can look at the init instead of the type of the variable, this
2358 // makes us more tolerant of the 'auto' deduced type.
2359 if (auto *VD = dyn_cast<VarDecl>(D)) {
2360 Expr *Init = VD->getInit();
2361 if (!Init || Init->getType().isNull())
2362 return nullptr;
2363
2364 const auto *RD = Init->getType()->getAsCXXRecordDecl();
2365 if (RD && RD->isGenericLambda())
2366 return RD->getDependentLambdaCallOperator()->getTemplatedDecl();
2367 if (RD && RD->isLambda())
2368 return RD->getLambdaCallOperator();
2369
2370 // FIXME: We could try harder in the case where this is a dependent thing
2371 // that ends up being a lambda (that is, the init is an unresolved lookup
2372 // expr), but we can't attach to the call/lookup expr. If we instead try to
2373 // attach to the VarDecl, when we go to instantiate it, attributes are
2374 // instantiated before the init, so we can't actually see the type at any
2375 // point where it would be relevant/able to be checked. We could perhaps do
2376 // some sort of 'after-init' instantiation/checking here, but that doesn't
2377 // seem valuable for a situation that other compilers don't handle.
2378 }
2379 return nullptr;
2380}
2381
2382void CreateRoutineDeclAttr(SemaOpenACC &SemaRef, SourceLocation DirLoc,
2384 ValueDecl *AddTo) {
2385 OpenACCRoutineDeclAttr *A =
2386 OpenACCRoutineDeclAttr::Create(SemaRef.getASTContext(), DirLoc);
2387 A->Clauses.assign(Clauses.begin(), Clauses.end());
2388 AddTo->addAttr(A);
2389}
2390} // namespace
2391
2392// Variant that adds attributes, because this is the unnamed case.
2395 Decl *NextParsedDecl) {
2396
2397 FunctionDecl *NextParsedFDecl = LegalizeNextParsedDecl(NextParsedDecl);
2398
2399 if (!NextParsedFDecl) {
2400 // If we don't have a valid 'next thing', just diagnose.
2401 SemaRef.Diag(DirLoc, diag::err_acc_decl_for_routine);
2402 return;
2403 }
2404
2405 // OpenACC 3.3 2.15:
2406 // In C and C++, function static variables are not supported in functions to
2407 // which a routine directive applies.
2408 if (auto Itr = MagicStaticLocs.find(NextParsedFDecl->getCanonicalDecl());
2409 Itr != MagicStaticLocs.end()) {
2410 Diag(Itr->second, diag::err_acc_magic_static_in_routine);
2411 Diag(DirLoc, diag::note_acc_construct_here)
2413
2414 return;
2415 }
2416
2417 auto BindItr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCBindClause>);
2418 for (auto *A : NextParsedFDecl->attrs()) {
2419 // OpenACC 3.3 2.15:
2420 // If a procedure has a bind clause on both the declaration and definition
2421 // than they both must bind to the same name.
2422 if (auto *RA = dyn_cast<OpenACCRoutineDeclAttr>(A)) {
2423 auto OtherBindItr =
2424 llvm::find_if(RA->Clauses, llvm::IsaPred<OpenACCBindClause>);
2425 if (OtherBindItr != RA->Clauses.end() &&
2426 (*cast<OpenACCBindClause>(*BindItr)) !=
2427 (*cast<OpenACCBindClause>(*OtherBindItr))) {
2428 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_unnamed_bind);
2429 Diag((*OtherBindItr)->getEndLoc(), diag::note_acc_previous_clause_here)
2430 << (*BindItr)->getClauseKind();
2431 return;
2432 }
2433 }
2434
2435 // OpenACC 3.3 2.15:
2436 // A bind clause may not bind to a routine name that has a visible bind
2437 // clause.
2438 // We take the combo of these two 2.15 restrictions to mean that the
2439 // 'declaration'/'definition' quote is an exception to this. So we're going
2440 // to disallow mixing of the two types entirely.
2441 if (auto *RA = dyn_cast<OpenACCRoutineAnnotAttr>(A);
2442 RA && RA->getRange().getEnd().isValid()) {
2443 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_bind);
2444 Diag(RA->getRange().getEnd(), diag::note_acc_previous_clause_here)
2445 << "bind";
2446 return;
2447 }
2448 }
2449
2450 CreateRoutineDeclAttr(*this, DirLoc, Clauses, NextParsedFDecl);
2451}
2452
2453// Variant that adds a decl, because this is the named case.
2455 SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
2456 Expr *FuncRef, SourceLocation RParenLoc,
2458 assert(LParenLoc.isValid());
2459
2460 if (FunctionDecl *FD = getFunctionFromRoutineName(FuncRef)) {
2461 // OpenACC 3.3 2.15:
2462 // In C and C++, function static variables are not supported in functions to
2463 // which a routine directive applies.
2464 if (auto Itr = MagicStaticLocs.find(FD->getCanonicalDecl());
2465 Itr != MagicStaticLocs.end()) {
2466 Diag(Itr->second, diag::err_acc_magic_static_in_routine);
2467 Diag(DirLoc, diag::note_acc_construct_here)
2469
2470 return nullptr;
2471 }
2472
2473 // OpenACC 3.3 2.15:
2474 // A bind clause may not bind to a routine name that has a visible bind
2475 // clause.
2476 auto BindItr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCBindClause>);
2477 SourceLocation BindLoc;
2478 if (BindItr != Clauses.end()) {
2479 BindLoc = (*BindItr)->getBeginLoc();
2480 // Since this is adding a 'named' routine, we aren't allowed to combine
2481 // with ANY other visible bind clause. Error if we see either.
2482
2483 for (auto *A : FD->attrs()) {
2484 if (auto *RA = dyn_cast<OpenACCRoutineDeclAttr>(A)) {
2485 auto OtherBindItr =
2486 llvm::find_if(RA->Clauses, llvm::IsaPred<OpenACCBindClause>);
2487 if (OtherBindItr != RA->Clauses.end()) {
2488 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_bind);
2489 Diag((*OtherBindItr)->getEndLoc(),
2490 diag::note_acc_previous_clause_here)
2491 << (*BindItr)->getClauseKind();
2492 return nullptr;
2493 }
2494 }
2495
2496 if (auto *RA = dyn_cast<OpenACCRoutineAnnotAttr>(A);
2497 RA && RA->getRange().getEnd().isValid()) {
2498 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_bind);
2499 Diag(RA->getRange().getEnd(), diag::note_acc_previous_clause_here)
2500 << (*BindItr)->getClauseKind();
2501 return nullptr;
2502 }
2503 }
2504 }
2505
2506 // Set the end-range to the 'bind' clause here, so we can look it up
2507 // later.
2508 auto *RAA = OpenACCRoutineAnnotAttr::CreateImplicit(getASTContext(),
2509 {DirLoc, BindLoc});
2510 FD->addAttr(RAA);
2511 // In case we are referencing not the 'latest' version, make sure we add
2512 // the attribute to all declarations.
2513 while (FD != FD->getMostRecentDecl()) {
2514 FD = FD->getMostRecentDecl();
2515 FD->addAttr(RAA);
2516 }
2517 }
2518
2519 LastRoutineDecl = OpenACCRoutineDecl::Create(
2520 getASTContext(), getCurContext(), StartLoc, DirLoc, LParenLoc, FuncRef,
2521 RParenLoc, EndLoc, Clauses);
2522 LastRoutineDecl->setAccess(AS_public);
2523 getCurContext()->addDecl(LastRoutineDecl);
2524
2525 return LastRoutineDecl;
2526}
2527
2529 SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
2530 Expr *ReferencedFunc, SourceLocation RParenLoc,
2532 DeclGroupPtrTy NextDecl) {
2533 assert((!ReferencedFunc || !NextDecl) &&
2534 "Only one of these should be filled");
2535
2536 if (LParenLoc.isInvalid()) {
2537 Decl *NextLineDecl = nullptr;
2538 if (NextDecl && NextDecl.get().isSingleDecl())
2539 NextLineDecl = NextDecl.get().getSingleDecl();
2540
2541 CheckRoutineDecl(DirLoc, Clauses, NextLineDecl);
2542
2543 return NextDecl.get();
2544 }
2545
2547 StartLoc, DirLoc, LParenLoc, ReferencedFunc, RParenLoc, Clauses, EndLoc)};
2548}
2549
2551 SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
2552 Expr *ReferencedFunc, SourceLocation RParenLoc,
2554 Stmt *NextStmt) {
2555 assert((!ReferencedFunc || !NextStmt) &&
2556 "Only one of these should be filled");
2557
2558 if (LParenLoc.isInvalid()) {
2559 Decl *NextLineDecl = nullptr;
2560 if (NextStmt)
2561 if (DeclStmt *DS = dyn_cast<DeclStmt>(NextStmt); DS && DS->isSingleDecl())
2562 NextLineDecl = DS->getSingleDecl();
2563
2564 CheckRoutineDecl(DirLoc, Clauses, NextLineDecl);
2565 return NextStmt;
2566 }
2567
2568 DeclGroupRef DR{CheckRoutineDecl(StartLoc, DirLoc, LParenLoc, ReferencedFunc,
2569 RParenLoc, Clauses, EndLoc)};
2570 return SemaRef.ActOnDeclStmt(DeclGroupPtrTy::make(DR), StartLoc, EndLoc);
2571}
2572
2573OpenACCRoutineDeclAttr *
2574SemaOpenACC::mergeRoutineDeclAttr(const OpenACCRoutineDeclAttr &Old) {
2575 OpenACCRoutineDeclAttr *New =
2576 OpenACCRoutineDeclAttr::Create(getASTContext(), Old.getLocation());
2577 // We should jsut be able to copy these, there isn't really any
2578 // merging/inheriting we have to do, so no worry about doing a deep copy.
2579 New->Clauses = Old.Clauses;
2580 return New;
2581}
2584 return OpenACCAsteriskSizeExpr::Create(getASTContext(), AsteriskLoc);
2585}
2586
2589 return BuildOpenACCAsteriskSizeExpr(AsteriskLoc);
2590}
2591
2592/// Loops through a type and generates an appropriate InitListExpr to generate
2593/// type initialization.
2595 SourceRange ExprRange,
2596 QualType Ty) {
2597 Ty = Ty.getCanonicalType();
2599
2600 if (const RecordDecl *RD = Ty->getAsRecordDecl()) {
2601 for (auto *F : RD->fields()) {
2602 if (Expr *NewExpr =
2603 GenerateReductionInitRecipeExpr(Context, ExprRange, F->getType()))
2604 Exprs.push_back(NewExpr);
2605 else
2606 return nullptr;
2607 }
2608 } else if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) {
2609 for (uint64_t Idx = 0; Idx < AT->getZExtSize(); ++Idx) {
2610 if (Expr *NewExpr = GenerateReductionInitRecipeExpr(Context, ExprRange,
2611 AT->getElementType()))
2612 Exprs.push_back(NewExpr);
2613 else
2614 return nullptr;
2615 }
2616
2617 } else if (Ty->isPointerType()) {
2618 // For now, we are going to punt/not initialize pointer types, as
2619 // discussions/designs are ongoing on how to express this behavior,
2620 // particularly since they probably need the 'bounds' passed to them
2621 // correctly. A future patch/patch set will go through all of the pointer
2622 // values for all of the recipes to make sure we have a sane behavior.
2623
2624 // For now, this will result in a NYI during code generation for
2625 // no-initializer.
2626 return nullptr;
2627 } else {
2628 assert(Ty->isScalarType());
2629
2630 // TODO: OpenACC: This currently only works for '1', but we need to figure
2631 // out a way to do least/largest/all-1s.
2632 if (Ty->isFloatingType()) {
2633 Exprs.push_back(FloatingLiteral::Create(
2634 Context, llvm::APFloat::getOne(Context.getFloatTypeSemantics(Ty)),
2635 /*isExact=*/true, Ty, ExprRange.getBegin()));
2636 } else {
2637 Exprs.push_back(IntegerLiteral::Create(
2638 Context, llvm::APInt(Context.getTypeSize(Ty), 1), Ty,
2639 ExprRange.getBegin()));
2640 }
2641 }
2642
2643 Expr *InitExpr = new (Context)
2644 InitListExpr(Context, ExprRange.getBegin(), Exprs, ExprRange.getEnd());
2645 InitExpr->setType(Ty);
2646 return InitExpr;
2647}
2648
2649std::pair<VarDecl *, VarDecl *>
2651 OpenACCReductionOperator ReductionOperator,
2652 const Expr *VarExpr) {
2653 // Strip off any array subscripts/array section exprs to get to the type of
2654 // the variable.
2655 while (isa_and_present<ArraySectionExpr, ArraySubscriptExpr>(VarExpr)) {
2656 if (const auto *AS = dyn_cast<ArraySectionExpr>(VarExpr))
2657 VarExpr = AS->getBase()->IgnoreParenImpCasts();
2658 else if (const auto *Sub = dyn_cast<ArraySubscriptExpr>(VarExpr))
2659 VarExpr = Sub->getBase()->IgnoreParenImpCasts();
2660 }
2661
2662 // If for some reason the expression is invalid, or this is dependent, just
2663 // fill in with nullptr. We'll count on TreeTransform to make this if
2664 // necessary.
2665 if (!VarExpr || VarExpr->getType()->isDependentType())
2666 return {nullptr, nullptr};
2667
2668 QualType VarTy =
2670
2671 IdentifierInfo *VarName = [&]() {
2672 switch (CK) {
2674 return &getASTContext().Idents.get("openacc.private.init");
2676 return &getASTContext().Idents.get("openacc.firstprivate.init");
2678 return &getASTContext().Idents.get("openacc.reduction.init");
2679 default:
2680 llvm_unreachable("Unknown clause kind?");
2681 }
2682 }();
2683
2684 VarDecl *Recipe = VarDecl::Create(
2686 VarExpr->getBeginLoc(), VarName, VarTy,
2687 getASTContext().getTrivialTypeSourceInfo(VarTy), SC_Auto);
2688
2690 VarDecl *Temporary = nullptr;
2691 {
2692 // Trap errors so we don't get weird ones here. If we can't init, we'll just
2693 // swallow the errors.
2696
2697 auto FinishValueInit = [&](Expr *InitExpr) {
2698 if (InitExpr) {
2700 Recipe->getLocation(), /*DirectInit=*/true, InitExpr);
2701 InitializationSequence InitSeq(SemaRef.SemaRef, Entity, Kind, InitExpr,
2702 /*TopLevelOfInitList=*/false,
2703 /*TreatUnavailableAsInvalid=*/false);
2704 return InitSeq.Perform(SemaRef.SemaRef, Entity, Kind, InitExpr, &VarTy);
2705 }
2706 return ExprEmpty();
2707 };
2708
2709 if (CK == OpenACCClauseKind::Private) {
2710 InitializationKind Kind =
2712
2713 InitializationSequence InitSeq(SemaRef.SemaRef, Entity, Kind, {});
2714 Init = InitSeq.Perform(SemaRef.SemaRef, Entity, Kind, {});
2715 } else if (CK == OpenACCClauseKind::FirstPrivate) {
2716 // Create a VarDecl to be the 'copied-from' for the copy section of the
2717 // recipe. This allows us to make the association so that we can use the
2718 // standard 'generation' ability of the init.
2719 Temporary = VarDecl::Create(
2721 VarExpr->getBeginLoc(), &getASTContext().Idents.get("openacc.temp"),
2722 VarTy, getASTContext().getTrivialTypeSourceInfo(VarTy), SC_Auto);
2723 auto *TemporaryDRE = DeclRefExpr::Create(
2725 Temporary,
2726 /*ReferstoEnclosingVariableOrCapture=*/false,
2728 VarExpr->getBeginLoc()},
2729 VarTy, clang::VK_LValue, Temporary, nullptr, NOUR_None);
2730
2731 Expr *InitExpr = nullptr;
2732
2733 if (const auto *ArrTy = getASTContext().getAsConstantArrayType(VarTy)) {
2734 // Arrays need to have each individual element initialized as there
2735 // isn't a normal 'equals' feature in C/C++. This section sets these up
2736 // as an init list after 'initializing' each individual element.
2738
2739 // Decay to pointer for the array subscript expression.
2740 auto *CastToPtr = ImplicitCastExpr::Create(
2741 getASTContext(),
2742 getASTContext().getPointerType(ArrTy->getElementType()),
2743 CK_ArrayToPointerDecay, TemporaryDRE, /*BasePath=*/nullptr,
2745
2746 for (std::size_t I = 0; I < ArrTy->getLimitedSize(); ++I) {
2747 // Each element needs to be some sort of copy initialization from an
2748 // array-index of the original temporary (referenced via a
2749 // DeclRefExpr).
2750
2751 auto *Idx = IntegerLiteral::Create(
2752 getASTContext(),
2753 llvm::APInt(
2754 getASTContext().getTypeSize(getASTContext().getSizeType()),
2755 I),
2756 getASTContext().getSizeType(), VarExpr->getBeginLoc());
2757
2758 Expr *Subscript = new (getASTContext()) ArraySubscriptExpr(
2759 CastToPtr, Idx, ArrTy->getElementType(), clang::VK_LValue,
2760 OK_Ordinary, VarExpr->getBeginLoc());
2761
2762 // Generate a simple copy from the result of the subscript. This will
2763 // do a bitwise copy or a copy-constructor, as necessary.
2764 InitializedEntity CopyEntity =
2766 InitializationKind CopyKind =
2768 InitializationSequence CopySeq(SemaRef.SemaRef, CopyEntity, CopyKind,
2769 Subscript,
2770 /*TopLevelOfInitList=*/true);
2771
2772 ExprResult ElemRes =
2773 CopySeq.Perform(SemaRef.SemaRef, CopyEntity, CopyKind, Subscript);
2774 Args.push_back(ElemRes.get());
2775 }
2776
2777 InitExpr = new (getASTContext())
2778 InitListExpr(getASTContext(), VarExpr->getBeginLoc(), Args,
2779 VarExpr->getEndLoc());
2780 InitExpr->setType(VarTy);
2781
2782 } else {
2783 // If this isn't an array, we can just do normal copy init from a simple
2784 // variable reference, so set that up.
2785 InitExpr = TemporaryDRE;
2786 }
2787
2788 Init = FinishValueInit(InitExpr);
2789 } else if (CK == OpenACCClauseKind::Reduction) {
2790 // How we initialize the reduction variable depends on the operator used,
2791 // according to the chart in OpenACC 3.3 section 2.6.15.
2792
2793 switch (ReductionOperator) {
2795 // This can only happen when there is an error, and since these inits
2796 // are used for code generation, we can just ignore/not bother doing any
2797 // initialization here.
2798 break;
2802 // TODO: OpenACC: figure out init for these.
2803 break;
2804
2807 // '&&' initializes every field to 1. However, we need to loop through
2808 // every field/element and generate an initializer for each of the
2809 // elements.
2810
2812 getASTContext(), VarExpr->getSourceRange(), VarTy);
2813
2814 Init = FinishValueInit(InitExpr);
2815 break;
2816 }
2821 // +, |, ^, and || all use 0 for their initializers, so we can just
2822 // use 'zero init' here and not bother with the rest of the
2823 // array/compound type/etc contents.
2824 Expr *InitExpr = new (getASTContext()) InitListExpr(
2825 getASTContext(), VarExpr->getBeginLoc(), {}, VarExpr->getEndLoc());
2826 // we set this to void so that the initialization sequence generation
2827 // will get this type correct/etc.
2828 InitExpr->setType(getASTContext().VoidTy);
2829
2830 Init = FinishValueInit(InitExpr);
2831 break;
2832 }
2833 }
2834 } else {
2835 llvm_unreachable("Unknown clause kind in CreateInitRecipe");
2836 }
2837 }
2838
2839 if (Init.get()) {
2840 Recipe->setInit(Init.get());
2842 }
2843
2844 return {Recipe, Temporary};
2845}
const Decl * D
Expr * E
This file defines OpenACC nodes for declarative directives.
Defines some OpenACC-specific enums and functions.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
SourceLocation Loc
Definition: SemaObjC.cpp:754
static Expr * GenerateReductionInitRecipeExpr(ASTContext &Context, SourceRange ExprRange, QualType Ty)
Loops through a type and generates an appropriate InitListExpr to generate type initialization.
This file declares semantic analysis for OpenACC constructs and clauses.
Defines the SourceManager interface.
This file defines OpenACC AST classes for statement-level contructs.
a trap message and trap category.
APSInt & getInt()
Definition: APValue.h:489
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
const ConstantArrayType * getAsConstantArrayType(QualType T) const
Definition: ASTContext.h:3056
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
CanQualType DependentTy
Definition: ASTContext.h:1250
IdentifierTable & Idents
Definition: ASTContext.h:740
CanQualType ArraySectionTy
Definition: ASTContext.h:1262
CanQualType IntTy
Definition: ASTContext.h:1231
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2625
CanQualType VoidTy
Definition: ASTContext.h:1222
PtrTy get() const
Definition: Ownership.h:171
bool isInvalid() const
Definition: Ownership.h:167
bool isUsable() const
Definition: Ownership.h:169
This class represents BOTH the OpenMP Array Section and OpenACC 'subarray', with a boolean differenti...
Definition: Expr.h:7092
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition: Expr.cpp:5224
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2723
QualType getElementType() const
Definition: TypeBase.h:3750
Represents a base class of a C++ class.
Definition: DeclCXX.h:146
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2604
Represents a C++ conversion function within a class.
Definition: DeclCXX.h:2937
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
base_class_range bases()
Definition: DeclCXX.h:608
Represents the canonical version of C arrays with a specified constant size.
Definition: TypeBase.h:3776
llvm::APInt getSize() const
Return the constant array size as an APInt.
Definition: TypeBase.h:3832
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1358
void addDecl(Decl *D)
Add the declaration D into this context.
Definition: DeclBase.cpp:1793
bool isStdNamespace() const
Definition: DeclBase.cpp:1342
DeclContext * getEnclosingNamespaceContext()
Retrieve the nearest enclosing namespace context.
Definition: DeclBase.cpp:2040
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Definition: Expr.cpp:484
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1611
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl.
Definition: Stmt.h:1624
const Decl * getSingleDecl() const
Definition: Stmt.h:1626
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
void addAttr(Attr *A)
Definition: DeclBase.cpp:1022
bool isInvalidDecl() const
Definition: DeclBase.h:588
void setAccess(AccessSpecifier AS)
Definition: DeclBase.h:502
SourceLocation getLocation() const
Definition: DeclBase.h:439
DeclContext * getDeclContext()
Definition: DeclBase.h:448
attr_range attrs() const
Definition: DeclBase.h:535
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:431
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Definition: DeclBase.h:918
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclBase.h:978
The name of a declaration.
bool isIdentifier() const
Predicate functions for querying what type of name this is.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Decl.h:830
This represents one expression.
Definition: Expr.h:112
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
void setType(QualType t)
Definition: Expr.h:145
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition: Expr.h:194
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3073
bool containsErrors() const
Whether this expression contains subexpressions which had errors.
Definition: Expr.h:246
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition: Expr.h:223
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:273
QualType getType() const
Definition: Expr.h:144
bool hasPlaceholderType() const
Returns whether this expression has a placeholder type.
Definition: Expr.h:523
Represents difference between two FPOptions values.
Definition: LangOptions.h:919
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
Definition: Expr.cpp:1072
Represents a function declaration or definition.
Definition: Decl.h:1999
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition: Decl.cpp:3688
bool isDeleted() const
Whether this function has been deleted.
Definition: Decl.h:2539
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition: Expr.cpp:2068
Describes an C or C++ initializer list.
Definition: Expr.h:5235
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateDefault(SourceLocation InitLoc)
Create a default initialization.
static InitializationKind CreateForInit(SourceLocation Loc, bool DirectInit, Expr *Init)
Create an initialization from an initializer (which, for direct initialization from a parenthesized l...
static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs=false)
Create a copy initialization.
Describes the sequence of initializations required to initialize a given object or reference with a s...
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
Definition: SemaInit.cpp:7739
Describes an entity that is being initialized.
static InitializedEntity InitializeElement(ASTContext &Context, unsigned Index, const InitializedEntity &Parent)
Create the initialization entity for an array element.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Definition: Expr.cpp:971
This represents a decl that may have a name.
Definition: Decl.h:273
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:300
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:339
A C++ nested-name-specifier augmented with source location information.
Wrapper for void* pointer.
Definition: Ownership.h:51
PtrTy get() const
Definition: Ownership.h:81
static OpaquePtr make(PtrTy P)
Definition: Ownership.h:61
static OpenACCAsteriskSizeExpr * Create(const ASTContext &C, SourceLocation Loc)
Definition: Expr.cpp:5469
static OpenACCAtomicConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, OpenACCAtomicKind AtKind, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *AssociatedStmt)
static OpenACCCacheConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation LParenLoc, SourceLocation ReadOnlyLoc, ArrayRef< Expr * > VarList, SourceLocation RParenLoc, SourceLocation End)
Represents a 'collapse' clause on a 'loop' construct.
const Expr * getLoopCount() const
static OpenACCCombinedConstruct * Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
Definition: StmtOpenACC.cpp:97
static OpenACCComputeConstruct * Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc, SourceLocation DirectiveLoc, SourceLocation EndLoc, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
Definition: StmtOpenACC.cpp:27
static OpenACCDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
static OpenACCDeclareDecl * Create(ASTContext &Ctx, DeclContext *DC, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation EndLoc, ArrayRef< const OpenACCClause * > Clauses)
Definition: DeclOpenACC.cpp:26
static OpenACCEnterDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCExitDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCHostDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
static OpenACCInitConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCLoopConstruct * Create(const ASTContext &C, OpenACCDirectiveKind ParentKind, SourceLocation BeginLoc, SourceLocation DirLoc, SourceLocation EndLoc, ArrayRef< const OpenACCClause * > Clauses, Stmt *Loop)
Definition: StmtOpenACC.cpp:75
static OpenACCRoutineDecl * Create(ASTContext &Ctx, DeclContext *DC, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, Expr *FuncRef, SourceLocation RParenLoc, SourceLocation EndLoc, ArrayRef< const OpenACCClause * > Clauses)
Definition: DeclOpenACC.cpp:43
const Expr * getFunctionReference() const
Definition: DeclOpenACC.h:147
static OpenACCSetConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCShutdownConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
ArrayRef< Expr * > getSizeExprs()
static OpenACCUpdateConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCWaitConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation LParenLoc, Expr *DevNumExpr, SourceLocation QueuesLoc, ArrayRef< Expr * > QueueIdExprs, SourceLocation RParenLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
A (possibly-)qualified type.
Definition: TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: TypeBase.h:1004
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition: TypeBase.h:8528
QualType getCanonicalType() const
Definition: TypeBase.h:8395
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: TypeBase.h:8437
Represents a struct/union/class.
Definition: Decl.h:4309
Base for LValueReferenceType and RValueReferenceType.
Definition: TypeBase.h:3589
Scope - A scope is a transient data structure that is used while parsing the program.
Definition: Scope.h:41
unsigned getDepth() const
Returns the depth of this scope. The translation-unit has scope depth 0.
Definition: Scope.h:339
bool isOpenACCLoopConstructScope() const
Definition: Scope.h:568
bool isDeclScope(const Decl *D) const
isDeclScope - Return true if this is the scope that the specified decl is declared in.
Definition: Scope.h:398
const Scope * getParent() const
getParent - Return the scope that this is nested in.
Definition: Scope.h:287
A generic diagnostic builder for errors which may or may not be deferred.
Definition: SemaBase.h:111
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:61
ASTContext & getASTContext() const
Definition: SemaBase.cpp:9
Sema & SemaRef
Definition: SemaBase.h:40
const LangOptions & getLangOpts() const
Definition: SemaBase.cpp:11
DeclContext * getCurContext() const
Definition: SemaBase.cpp:12
AssociatedStmtRAII(SemaOpenACC &, OpenACCDirectiveKind, SourceLocation, ArrayRef< const OpenACCClause * >, ArrayRef< OpenACCClause * >)
void SetTileInfoBeforeAssociatedStmt(ArrayRef< const OpenACCClause * > UnInstClauses, ArrayRef< OpenACCClause * > Clauses)
void SetCollapseInfoBeforeAssociatedStmt(ArrayRef< const OpenACCClause * > UnInstClauses, ArrayRef< OpenACCClause * > Clauses)
ExprResult ActOnRoutineName(Expr *RoutineName)
bool ActOnStartDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, ArrayRef< const OpenACCClause * > Clauses)
Called after the directive, including its clauses, have been parsed and parsing has consumed the 'ann...
ComputeConstructInfo & getActiveComputeConstructInfo()
Definition: SemaOpenACC.h:257
bool ActOnStartStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, ArrayRef< const OpenACCClause * > Clauses)
Called after the directive, including its clauses, have been parsed and parsing has consumed the 'ann...
ExprResult BuildOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc)
ExprResult ActOnIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK, SourceLocation Loc, Expr *IntExpr)
Called when encountering an 'int-expr' for OpenACC, and manages conversions and diagnostics to 'int'.
void ActOnVariableDeclarator(VarDecl *VD)
Function called when a variable declarator is created, which lets us implement the 'routine' 'functio...
void ActOnWhileStmt(SourceLocation WhileLoc)
SourceLocation LoopWorkerClauseLoc
If there is a current 'active' loop construct with a 'worker' clause on it (on any sort of construct)...
Definition: SemaOpenACC.h:274
DeclGroupRef ActOnEndRoutineDeclDirective(SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, Expr *ReferencedFunc, SourceLocation RParenLoc, ArrayRef< const OpenACCClause * > Clauses, SourceLocation EndLoc, DeclGroupPtrTy NextDecl)
void ActOnInvalidParseVar()
Called only if the parse of a 'var' was invalid, else 'ActOnVar' should be called.
void CheckRoutineDecl(SourceLocation DirLoc, ArrayRef< const OpenACCClause * > Clauses, Decl *NextParsedDecl)
bool CheckVarIsPointerType(OpenACCClauseKind ClauseKind, Expr *VarExpr)
Called to check the 'var' type is a variable of pointer type, necessary for 'deviceptr' and 'attach' ...
struct clang::SemaOpenACC::LoopGangOnKernelTy LoopGangClauseOnKernel
StmtResult ActOnEndRoutineStmtDirective(SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, Expr *ReferencedFunc, SourceLocation RParenLoc, ArrayRef< const OpenACCClause * > Clauses, SourceLocation EndLoc, Stmt *NextStmt)
void CheckDeclReference(SourceLocation Loc, Expr *E, Decl *D)
StmtResult ActOnAssociatedStmt(SourceLocation DirectiveLoc, OpenACCDirectiveKind K, OpenACCAtomicKind AtKind, ArrayRef< const OpenACCClause * > Clauses, StmtResult AssocStmt)
Called when we encounter an associated statement for our construct, this should check legality of the...
OpenACCRoutineDeclAttr * mergeRoutineDeclAttr(const OpenACCRoutineDeclAttr &Old)
void ActOnFunctionDeclarator(FunctionDecl *FD)
Called when a function decl is created, which lets us implement the 'routine' 'doesn't match next thi...
ExprResult ActOnCacheVar(Expr *VarExpr)
Helper function called by ActonVar that is used to check a 'cache' var.
struct clang::SemaOpenACC::LoopWithoutSeqCheckingInfo LoopWithoutSeqInfo
DeclGroupRef ActOnEndDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, SourceLocation RParenLoc, SourceLocation EndLoc, ArrayRef< OpenACCClause * > Clauses)
Called after the directive has been completely parsed, including the declaration group or associated ...
SourceLocation LoopVectorClauseLoc
If there is a current 'active' loop construct with a 'vector' clause on it (on any sort of construct)...
Definition: SemaOpenACC.h:279
ExprResult ActOnVar(OpenACCDirectiveKind DK, OpenACCClauseKind CK, Expr *VarExpr)
Called when encountering a 'var' for OpenACC, ensures it is actually a declaration reference to a var...
void ActOnConstruct(OpenACCDirectiveKind K, SourceLocation DirLoc)
Called after the construct has been parsed, but clauses haven't been parsed.
ExprResult ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc)
void ActOnDoStmt(SourceLocation DoLoc)
void ActOnVariableInit(VarDecl *VD, QualType InitType)
Called when a variable is initialized, so we can implement the 'routine 'doesn't match the next thing...
void ActOnRangeForStmtBegin(SourceLocation ForLoc, const Stmt *OldRangeFor, const Stmt *RangeFor)
void ActOnStartParseVar(OpenACCDirectiveKind DK, OpenACCClauseKind CK)
Called right before a 'var' is parsed, so we can set the state for parsing a 'cache' var.
StmtResult ActOnEndStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef< Expr * > Exprs, OpenACCAtomicKind AK, SourceLocation RParenLoc, SourceLocation EndLoc, ArrayRef< OpenACCClause * > Clauses, StmtResult AssocStmt)
Called after the directive has been completely parsed, including the declaration group or associated ...
void ActOnForStmtEnd(SourceLocation ForLoc, StmtResult Body)
StmtResult CheckAtomicAssociatedStmt(SourceLocation AtomicDirLoc, OpenACCAtomicKind AtKind, StmtResult AssocStmt)
Called to check the form of the atomic construct which has some fairly sizable restrictions.
void ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *First, const Stmt *Second, const Stmt *Third)
ExprResult ActOnArraySectionExpr(Expr *Base, SourceLocation LBLoc, Expr *LowerBound, SourceLocation ColonLocFirst, Expr *Length, SourceLocation RBLoc)
Checks and creates an Array Section used in an OpenACC construct/clause.
std::pair< VarDecl *, VarDecl * > CreateInitRecipe(OpenACCClauseKind CK, const Expr *VarExpr)
Definition: SemaOpenACC.h:246
SpecialMemberOverloadResult - The overloading result for a special member function.
Definition: Sema.h:9239
CXXMethodDecl * getMethod() const
Definition: Sema.h:9251
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition: Sema.h:12401
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:850
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition: Sema.h:1113
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)
Definition: SemaExpr.cpp:17664
ExprResult PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter)
Perform a contextual implicit conversion.
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
Definition: SemaExpr.cpp:748
ASTContext & getASTContext() const
Definition: Sema.h:918
void PopExpressionEvaluationContext()
Definition: SemaExpr.cpp:18155
ExprResult DefaultLvalueConversion(Expr *E)
Definition: SemaExpr.cpp:633
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
Definition: SemaExpr.cpp:21316
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
Definition: SemaStmt.cpp:75
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Definition: SemaType.cpp:9241
void DiscardCleanupsInEvaluationContext()
Definition: SemaExpr.cpp:18228
SourceManager & SourceMgr
Definition: Sema.h:1279
SpecialMemberOverloadResult LookupSpecialMember(CXXRecordDecl *D, CXXSpecialMemberKind SM, bool ConstArg, bool VolatileArg, bool RValueThis, bool ConstThis, bool VolatileThis)
ExprResult CreateRecoveryExpr(SourceLocation Begin, SourceLocation End, ArrayRef< Expr * > SubExprs, QualType T=QualType())
Attempts to produce a RecoveryExpr after some AST node cannot be created.
Definition: SemaExpr.cpp:21528
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
Definition: Stmt.h:85
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Stmt.cpp:358
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:334
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:346
bool isDependentSizedArrayType() const
Definition: TypeBase.h:8699
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.h:26
bool isConstantArrayType() const
Definition: TypeBase.h:8683
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition: Type.h:41
bool isArrayType() const
Definition: TypeBase.h:8679
bool isPointerType() const
Definition: TypeBase.h:8580
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: TypeBase.h:8980
bool isEnumeralType() const
Definition: TypeBase.h:8711
bool isScalarType() const
Definition: TypeBase.h:9038
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:752
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
Definition: TypeBase.h:8930
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition: TypeBase.h:2808
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: TypeBase.h:2800
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: TypeBase.h:9212
bool isFunctionType() const
Definition: TypeBase.h:8576
bool isFloatingType() const
Definition: Type.cpp:2308
bool isAnyPointerType() const
Definition: TypeBase.h:8588
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
bool isRecordType() const
Definition: TypeBase.h:8707
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:711
QualType getType() const
Definition: Decl.h:722
Represents a variable declaration or definition.
Definition: Decl.h:925
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition: Decl.cpp:2151
void setInitStyle(InitializationStyle Style)
Definition: Decl.h:1451
@ CallInit
Call-style initialization (C++98)
Definition: Decl.h:933
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition: Decl.h:1207
void setInit(Expr *I)
Definition: Decl.cpp:2477
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
The JSON file list parser is used to communicate input to InstallAPI.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
Definition: OperatorKinds.h:21
OpenACCDirectiveKind
Definition: OpenACCKinds.h:28
OpenACCReductionOperator
Definition: OpenACCKinds.h:547
@ Invalid
Invalid Reduction Clause Kind.
OpenACCAtomicKind
Definition: OpenACCKinds.h:172
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition: Specifiers.h:151
BinaryOperatorKind
OpenACCClauseKind
Represents the kind of an OpenACC clause.
Definition: OpenACCKinds.h:207
@ Collapse
'collapse' clause, allowed on 'loop' and Combined constructs.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Invalid
Represents an invalid clause, for the purposes of parsing.
@ UseDevice
'use_device' clause, allowed on 'host_data' construct.
@ Reduction
'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.
@ FirstPrivate
'firstprivate' clause, allowed on 'parallel', 'serial', 'parallel loop', and 'serial loop' constructs...
@ Tile
'tile' clause, allowed on 'loop' and Combined constructs.
@ AS_public
Definition: Specifiers.h:124
@ SC_Auto
Definition: Specifiers.h:256
ExprResult ExprEmpty()
Definition: Ownership.h:272
StmtResult StmtError()
Definition: Ownership.h:266
@ Result
The result type of a method or function.
ExprResult ExprError()
Definition: Ownership.h:265
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:139
const FunctionProtoType * T
@ NOUR_None
This is an odr-use.
Definition: Specifiers.h:175
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:645
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:647