clang  19.0.0git
SemaStmtAttr.cpp
Go to the documentation of this file.
1 //===--- SemaStmtAttr.cpp - Statement Attribute Handling ------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements stmt-related attribute processing.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/AST/ASTContext.h"
16 #include "clang/Basic/TargetInfo.h"
18 #include "clang/Sema/Lookup.h"
19 #include "clang/Sema/ScopeInfo.h"
21 #include "llvm/ADT/StringExtras.h"
22 #include <optional>
23 
24 using namespace clang;
25 using namespace sema;
26 
27 static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A,
28  SourceRange Range) {
29  FallThroughAttr Attr(S.Context, A);
30  if (isa<SwitchCase>(St)) {
31  S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_wrong_target)
32  << A << St->getBeginLoc();
34  S.Diag(L, diag::note_fallthrough_insert_semi_fixit)
35  << FixItHint::CreateInsertion(L, ";");
36  return nullptr;
37  }
38  auto *FnScope = S.getCurFunction();
39  if (FnScope->SwitchStack.empty()) {
40  S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_outside_switch);
41  return nullptr;
42  }
43 
44  // If this is spelled as the standard C++17 attribute, but not in C++17, warn
45  // about using it as an extension.
46  if (!S.getLangOpts().CPlusPlus17 && A.isCXX11Attribute() &&
47  !A.getScopeName())
48  S.Diag(A.getLoc(), diag::ext_cxx17_attr) << A;
49 
50  FnScope->setHasFallthroughStmt();
51  return ::new (S.Context) FallThroughAttr(S.Context, A);
52 }
53 
54 static Attr *handleSuppressAttr(Sema &S, Stmt *St, const ParsedAttr &A,
55  SourceRange Range) {
56  if (A.getAttributeSpellingListIndex() == SuppressAttr::CXX11_gsl_suppress &&
57  A.getNumArgs() < 1) {
58  // Suppression attribute with GSL spelling requires at least 1 argument.
59  S.Diag(A.getLoc(), diag::err_attribute_too_few_arguments) << A << 1;
60  return nullptr;
61  }
62 
63  std::vector<StringRef> DiagnosticIdentifiers;
64  for (unsigned I = 0, E = A.getNumArgs(); I != E; ++I) {
65  StringRef RuleName;
66 
67  if (!S.checkStringLiteralArgumentAttr(A, I, RuleName, nullptr))
68  return nullptr;
69 
70  DiagnosticIdentifiers.push_back(RuleName);
71  }
72 
73  return ::new (S.Context) SuppressAttr(
74  S.Context, A, DiagnosticIdentifiers.data(), DiagnosticIdentifiers.size());
75 }
76 
77 SYCLIntelMaxConcurrencyAttr *
79  Expr *E) {
80  if (!E->isValueDependent()) {
81  llvm::APSInt ArgVal;
82  ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal);
83  if (Res.isInvalid())
84  return nullptr;
85  E = Res.get();
86 
87  // This attribute requires a non-negative value.
88  if (ArgVal < 0) {
89  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
90  << CI << /*non-negative*/ 1;
91  return nullptr;
92  }
93  }
94 
95  return new (Context) SYCLIntelMaxConcurrencyAttr(Context, CI, E);
96 }
97 
99  const ParsedAttr &A) {
101 
102  Expr *E = A.getArgAsExpr(0);
103  return S.BuildSYCLIntelMaxConcurrencyAttr(A, E);
104 }
105 
106 SYCLIntelInitiationIntervalAttr *
108  Expr *E) {
109  if (!E->isValueDependent()) {
110  llvm::APSInt ArgVal;
111  ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal);
112  if (Res.isInvalid())
113  return nullptr;
114  E = Res.get();
115 
116  // This attribute requires a strictly positive value.
117  if (ArgVal <= 0) {
118  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
119  << CI << /*positive*/ 0;
120  return nullptr;
121  }
122  }
123 
124  return new (Context) SYCLIntelInitiationIntervalAttr(Context, CI, E);
125 }
126 
128  const ParsedAttr &A) {
130 
131  Expr *E = A.getArgAsExpr(0);
133 }
134 
135 SYCLIntelMaxInterleavingAttr *
137  Expr *E) {
138  if (!E->isValueDependent()) {
139  llvm::APSInt ArgVal;
140  ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal);
141  if (Res.isInvalid())
142  return nullptr;
143  E = Res.get();
144 
145  // This attribute accepts values 0 and 1 only.
146  if (ArgVal < 0 || ArgVal > 1) {
147  Diag(E->getBeginLoc(), diag::err_attribute_argument_is_not_valid) << CI;
148  return nullptr;
149  }
150  }
151 
152  return new (Context) SYCLIntelMaxInterleavingAttr(Context, CI, E);
153 }
154 
156  const ParsedAttr &A) {
158 
159  Expr *E = A.getArgAsExpr(0);
160  return S.BuildSYCLIntelMaxInterleavingAttr(A, E);
161 }
162 
163 SYCLIntelLoopCoalesceAttr *
165  Expr *E) {
166  if (E && !E->isValueDependent()) {
167  llvm::APSInt ArgVal;
168  ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal);
169  if (Res.isInvalid())
170  return nullptr;
171  E = Res.get();
172 
173  // This attribute requires a strictly positive value.
174  if (ArgVal <= 0) {
175  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
176  << CI << /*positive*/ 0;
177  return nullptr;
178  }
179  }
180 
181  return new (Context) SYCLIntelLoopCoalesceAttr(Context, CI, E);
182 }
183 
185  const ParsedAttr &A) {
187 
188  Expr *E = A.isArgExpr(0) ? A.getArgAsExpr(0) : nullptr;
189  return S.BuildSYCLIntelLoopCoalesceAttr(A, E);
190 }
191 
192 SYCLIntelSpeculatedIterationsAttr *
194  Expr *E) {
195  if (!E->isValueDependent()) {
196  llvm::APSInt ArgVal;
197  ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal);
198  if (Res.isInvalid())
199  return nullptr;
200  E = Res.get();
201 
202  // This attribute requires a non-negative value.
203  if (ArgVal < 0) {
204  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
205  << CI << /*non-negative*/ 1;
206  return nullptr;
207  }
208  }
209 
210  return new (Context) SYCLIntelSpeculatedIterationsAttr(Context, CI, E);
211 }
212 
214  const ParsedAttr &A) {
216 
217  Expr *E = A.getArgAsExpr(0);
219 }
220 
222  const ParsedAttr &A) {
224  return new (S.Context) SYCLIntelDisableLoopPipeliningAttr(S.Context, A);
225 }
226 
228  Expr *E) {
229  // This attribute requires a non-negative value.
230  if (!Value.isNonNegative())
231  return S.Diag(E->getExprLoc(),
232  diag::err_attribute_requires_positive_integer)
233  << "'ivdep'" << /*non-negative*/ 1;
234  return false;
235 }
236 
237 enum class IVDepExprResult {
238  Invalid,
239  Null,
240  Dependent,
241  Array,
242  SafeLen,
243 };
244 
246  unsigned &SafelenValue) {
247  if (!E)
248  return IVDepExprResult::Null;
249 
250  if (E->isInstantiationDependent())
252 
253  std::optional<llvm::APSInt> ArgVal = E->getIntegerConstantExpr(S.getASTContext());
254  if (ArgVal) {
255  if (checkSYCLIntelIVDepSafeLen(S, *ArgVal, E))
257  SafelenValue = ArgVal->getZExtValue();
258  // ivdep attribute allows both safelen = 0 and safelen = 1 with a warning.
259  if (SafelenValue == 0 || SafelenValue == 1) {
260  S.Diag(E->getExprLoc(), diag::warn_ivdep_attribute_argument)
261  << SafelenValue;
263  }
265  }
266 
267  if (isa<DeclRefExpr>(E) || isa<MemberExpr>(E)) {
268  if (!E->getType()->isArrayType() && !E->getType()->isPointerType()) {
269  S.Diag(E->getExprLoc(), diag::err_ivdep_declrefexpr_arg);
271  }
272  return IVDepExprResult::Array;
273  }
274 
275  S.Diag(E->getExprLoc(), diag::err_ivdep_unknown_arg);
277 }
278 
279 // Note: At the time of this call, we don't know the order of the expressions,
280 // so we name them vaguely until we can figure it out.
281 SYCLIntelIVDepAttr *
283  Expr *Expr2) {
284  unsigned SafelenValue = 0;
285  IVDepExprResult E1 = HandleIVDepAttrExpr(*this, Expr1, SafelenValue);
286  IVDepExprResult E2 = HandleIVDepAttrExpr(*this, Expr2, SafelenValue);
287 
289  return nullptr;
290 
291  if (E1 == E2 && E1 != IVDepExprResult::Dependent &&
292  E1 != IVDepExprResult::Null) {
293  Diag(Expr2->getExprLoc(), diag::err_ivdep_duplicate_arg);
294  return nullptr;
295  }
296 
297  // Try to put Safelen in the 1st one so codegen can count on the ordering.
298  Expr *SafeLenExpr = Expr1;
299  Expr *ArrayExpr = Expr2;
300 
301  // Both can be null or dependent, so swap if we're really sure.
303  SafeLenExpr = Expr2;
304  ArrayExpr = Expr1;
305  }
306 
307  return new (Context)
308  SYCLIntelIVDepAttr(Context, CI, SafeLenExpr, ArrayExpr, SafelenValue);
309 }
310 
311 // Filters out any attributes from the list that are either not the specified
312 // type, or whose function isDependent returns true.
313 template <typename T>
315  SmallVectorImpl<const T *> &FilteredAttrs) {
316 
317  llvm::transform(Attrs, std::back_inserter(FilteredAttrs),
318  [](const Attr *A) -> const T * {
319  if (const auto *Cast = dyn_cast<T>(A))
320  return Cast->isDependent() ? nullptr : Cast;
321  return nullptr;
322  });
323  FilteredAttrs.erase(
324  std::remove(FilteredAttrs.begin(), FilteredAttrs.end(), nullptr),
325  FilteredAttrs.end());
326 }
327 
328 static void
330  // Skip SEMA if we're in a template, this will be diagnosed later.
332  return;
333 
335  // Filter down to just non-dependent ivdeps.
336  FilterAttributeList(Attrs, FilteredAttrs);
337  if (FilteredAttrs.empty())
338  return;
339 
340  SmallVector<const SYCLIntelIVDepAttr *, 8> SortedAttrs(FilteredAttrs);
341  llvm::stable_sort(SortedAttrs, SYCLIntelIVDepAttr::SafelenCompare);
342 
343  // Find the maximum without an array expression, which ends up in the 2nd
344  // expr.
345  const auto *GlobalMaxItr =
346  llvm::find_if(SortedAttrs, [](const SYCLIntelIVDepAttr *A) {
347  return !A->getArrayExpr();
348  });
349  const SYCLIntelIVDepAttr *GlobalMax =
350  GlobalMaxItr == SortedAttrs.end() ? nullptr : *GlobalMaxItr;
351 
352  for (const auto *A : FilteredAttrs) {
353  if (A == GlobalMax)
354  continue;
355 
356  if (GlobalMax && !SYCLIntelIVDepAttr::SafelenCompare(A, GlobalMax)) {
357  S.Diag(A->getLocation(), diag::warn_ivdep_redundant)
358  << !GlobalMax->isInf() << GlobalMax->getSafelenValue() << !A->isInf()
359  << A->getSafelenValue();
360  S.Diag(GlobalMax->getLocation(), diag::note_previous_attribute);
361  continue;
362  }
363 
364  if (!A->getArrayExpr())
365  continue;
366 
367  const ValueDecl *ArrayDecl = A->getArrayDecl();
368  auto Other = llvm::find_if(SortedAttrs,
369  [ArrayDecl](const SYCLIntelIVDepAttr *A) {
370  return ArrayDecl == A->getArrayDecl();
371  });
372  assert(Other != SortedAttrs.end() && "Should find at least itself");
373 
374  // Diagnose if lower/equal to the lowest with this array.
375  if (*Other != A && !SYCLIntelIVDepAttr::SafelenCompare(A, *Other)) {
376  S.Diag(A->getLocation(), diag::warn_ivdep_redundant)
377  << !(*Other)->isInf() << (*Other)->getSafelenValue() << !A->isInf()
378  << A->getSafelenValue();
379  S.Diag((*Other)->getLocation(), diag::note_previous_attribute);
380  }
381  }
382 }
383 
384 static Attr *handleIntelIVDepAttr(Sema &S, Stmt *St, const ParsedAttr &A) {
385  unsigned NumArgs = A.getNumArgs();
386 
388 
389  return S.BuildSYCLIntelIVDepAttr(
390  A, NumArgs >= 1 ? A.getArgAsExpr(0) : nullptr,
391  NumArgs == 2 ? A.getArgAsExpr(1) : nullptr);
392 }
393 
394 static void
396  ArrayRef<const Attr *> Attrs) {
397  // Create a list of SYCLIntelLoopCount attributes only.
399  llvm::transform(
400  Attrs, std::back_inserter(OnlyLoopCountAttrs), [](const Attr *A) {
401  return dyn_cast_or_null<const SYCLIntelLoopCountAttr>(A);
402  });
403  OnlyLoopCountAttrs.erase(
404  std::remove(OnlyLoopCountAttrs.begin(), OnlyLoopCountAttrs.end(),
405  static_cast<const SYCLIntelLoopCountAttr *>(nullptr)),
406  OnlyLoopCountAttrs.end());
407  if (OnlyLoopCountAttrs.empty())
408  return;
409 
410  unsigned int MinCount = 0;
411  unsigned int MaxCount = 0;
412  unsigned int AvgCount = 0;
413  unsigned int Count = 0;
414  for (const auto *A : OnlyLoopCountAttrs) {
415  const auto *At = dyn_cast<SYCLIntelLoopCountAttr>(A);
416  At->isMin() ? MinCount++
417  : At->isMax() ? MaxCount++
418  : At->isAvg() ? AvgCount++
419  : Count++;
420  if (MinCount > 1 || MaxCount > 1 || AvgCount > 1 || Count > 1)
421  S.Diag(A->getLocation(), diag::err_sycl_loop_attr_duplication) << 1 << A;
422  }
423 }
424 
425 SYCLIntelLoopCountAttr *
427  if (!E->isValueDependent()) {
428  llvm::APSInt ArgVal;
429  ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal);
430  if (Res.isInvalid())
431  return nullptr;
432  E = Res.get();
433 
434  // This attribute requires a non-negative value.
435  if (ArgVal < 0) {
436  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
437  << CI << /*non-negative*/ 1;
438  return nullptr;
439  }
440  }
441 
442  return new (Context) SYCLIntelLoopCountAttr(Context, CI, E);
443 }
444 
446  const ParsedAttr &A) {
448 
449  Expr *E = A.getArgAsExpr(0);
450  return S.BuildSYCLIntelLoopCountAttr(A, E);
451 }
452 
454  const ParsedAttr &A) {
455  return new (S.Context) SYCLIntelNofusionAttr(S.Context, A);
456 }
457 
458 SYCLIntelMaxReinvocationDelayAttr *
460  Expr *E) {
461  if (!E->isValueDependent()) {
462  llvm::APSInt ArgVal;
463  ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal);
464  if (Res.isInvalid())
465  return nullptr;
466  E = Res.get();
467 
468  // This attribute requires a strictly positive value.
469  if (ArgVal <= 0) {
470  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
471  << CI << /*positive*/ 0;
472  return nullptr;
473  }
474  }
475 
476  return new (Context) SYCLIntelMaxReinvocationDelayAttr(Context, CI, E);
477 }
478 
480  const ParsedAttr &A) {
482 
483  Expr *E = A.getArgAsExpr(0);
485 }
486 
488  const ParsedAttr &A) {
489  return new (S.Context) SYCLIntelEnableLoopPipeliningAttr(S.Context, A);
490 }
491 
492 static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
493  SourceRange) {
494  IdentifierLoc *PragmaNameLoc = A.getArgAsIdent(0);
495  IdentifierLoc *OptionLoc = A.getArgAsIdent(1);
496  IdentifierLoc *StateLoc = A.getArgAsIdent(2);
497  Expr *ValueExpr = A.getArgAsExpr(3);
498 
499  StringRef PragmaName =
500  llvm::StringSwitch<StringRef>(PragmaNameLoc->Ident->getName())
501  .Cases("unroll", "nounroll", "unroll_and_jam", "nounroll_and_jam",
502  PragmaNameLoc->Ident->getName())
503  .Default("clang loop");
504 
505  // This could be handled automatically by adding a Subjects definition in
506  // Attr.td, but that would make the diagnostic behavior worse in this case
507  // because the user spells this attribute as a pragma.
508  if (!isa<DoStmt, ForStmt, CXXForRangeStmt, WhileStmt>(St)) {
509  std::string Pragma = "#pragma " + std::string(PragmaName);
510  S.Diag(St->getBeginLoc(), diag::err_pragma_loop_precedes_nonloop) << Pragma;
511  return nullptr;
512  }
513 
514  LoopHintAttr::OptionType Option;
515  LoopHintAttr::LoopHintState State;
516 
517  auto SetHints = [&Option, &State](LoopHintAttr::OptionType O,
518  LoopHintAttr::LoopHintState S) {
519  Option = O;
520  State = S;
521  };
522 
523  if (PragmaName == "nounroll") {
524  SetHints(LoopHintAttr::Unroll, LoopHintAttr::Disable);
525  } else if (PragmaName == "unroll") {
526  // #pragma unroll N
527  if (ValueExpr) {
528  if (!ValueExpr->isValueDependent()) {
529  auto Value = ValueExpr->EvaluateKnownConstInt(S.getASTContext());
530  if (Value.isZero() || Value.isOne())
531  SetHints(LoopHintAttr::Unroll, LoopHintAttr::Disable);
532  else
533  SetHints(LoopHintAttr::UnrollCount, LoopHintAttr::Numeric);
534  } else
535  SetHints(LoopHintAttr::UnrollCount, LoopHintAttr::Numeric);
536  } else
537  SetHints(LoopHintAttr::Unroll, LoopHintAttr::Enable);
538  } else if (PragmaName == "nounroll_and_jam") {
539  SetHints(LoopHintAttr::UnrollAndJam, LoopHintAttr::Disable);
540  } else if (PragmaName == "unroll_and_jam") {
541  // #pragma unroll_and_jam N
542  if (ValueExpr)
543  SetHints(LoopHintAttr::UnrollAndJamCount, LoopHintAttr::Numeric);
544  else
545  SetHints(LoopHintAttr::UnrollAndJam, LoopHintAttr::Enable);
546  } else {
547  // #pragma clang loop ...
548  assert(OptionLoc && OptionLoc->Ident &&
549  "Attribute must have valid option info.");
550  Option = llvm::StringSwitch<LoopHintAttr::OptionType>(
551  OptionLoc->Ident->getName())
552  .Case("vectorize", LoopHintAttr::Vectorize)
553  .Case("vectorize_width", LoopHintAttr::VectorizeWidth)
554  .Case("interleave", LoopHintAttr::Interleave)
555  .Case("vectorize_predicate", LoopHintAttr::VectorizePredicate)
556  .Case("interleave_count", LoopHintAttr::InterleaveCount)
557  .Case("unroll", LoopHintAttr::Unroll)
558  .Case("unroll_count", LoopHintAttr::UnrollCount)
559  .Case("pipeline", LoopHintAttr::PipelineDisabled)
560  .Case("pipeline_initiation_interval",
561  LoopHintAttr::PipelineInitiationInterval)
562  .Case("distribute", LoopHintAttr::Distribute)
563  .Default(LoopHintAttr::Vectorize);
564  if (Option == LoopHintAttr::VectorizeWidth) {
565  assert((ValueExpr || (StateLoc && StateLoc->Ident)) &&
566  "Attribute must have a valid value expression or argument.");
567  if (ValueExpr && S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc(),
568  /*AllowZero=*/false))
569  return nullptr;
570  if (StateLoc && StateLoc->Ident && StateLoc->Ident->isStr("scalable"))
571  State = LoopHintAttr::ScalableWidth;
572  else
573  State = LoopHintAttr::FixedWidth;
574  } else if (Option == LoopHintAttr::InterleaveCount ||
575  Option == LoopHintAttr::UnrollCount ||
576  Option == LoopHintAttr::PipelineInitiationInterval) {
577  assert(ValueExpr && "Attribute must have a valid value expression.");
578  if (S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc(),
579  /*AllowZero=*/false))
580  return nullptr;
581  State = LoopHintAttr::Numeric;
582  } else if (Option == LoopHintAttr::Vectorize ||
583  Option == LoopHintAttr::Interleave ||
584  Option == LoopHintAttr::VectorizePredicate ||
585  Option == LoopHintAttr::Unroll ||
586  Option == LoopHintAttr::Distribute ||
587  Option == LoopHintAttr::PipelineDisabled) {
588  assert(StateLoc && StateLoc->Ident && "Loop hint must have an argument");
589  if (StateLoc->Ident->isStr("disable"))
590  State = LoopHintAttr::Disable;
591  else if (StateLoc->Ident->isStr("assume_safety"))
592  State = LoopHintAttr::AssumeSafety;
593  else if (StateLoc->Ident->isStr("full"))
594  State = LoopHintAttr::Full;
595  else if (StateLoc->Ident->isStr("enable"))
596  State = LoopHintAttr::Enable;
597  else
598  llvm_unreachable("bad loop hint argument");
599  } else
600  llvm_unreachable("bad loop hint");
601  }
602 
603  return LoopHintAttr::CreateImplicit(S.Context, Option, State, ValueExpr, A);
604 }
605 
606 namespace {
607 class CallExprFinder : public ConstEvaluatedExprVisitor<CallExprFinder> {
608  bool FoundAsmStmt = false;
609  std::vector<const CallExpr *> CallExprs;
610 
611 public:
613 
614  CallExprFinder(Sema &S, const Stmt *St) : Inherited(S.Context) { Visit(St); }
615 
616  bool foundCallExpr() { return !CallExprs.empty(); }
617  const std::vector<const CallExpr *> &getCallExprs() { return CallExprs; }
618 
619  bool foundAsmStmt() { return FoundAsmStmt; }
620 
621  void VisitCallExpr(const CallExpr *E) { CallExprs.push_back(E); }
622 
623  void VisitAsmStmt(const AsmStmt *S) { FoundAsmStmt = true; }
624 
625  void Visit(const Stmt *St) {
626  if (!St)
627  return;
629  }
630 };
631 } // namespace
632 
633 static Attr *handleNoMergeAttr(Sema &S, Stmt *St, const ParsedAttr &A,
634  SourceRange Range) {
635  NoMergeAttr NMA(S.Context, A);
636  CallExprFinder CEF(S, St);
637 
638  if (!CEF.foundCallExpr() && !CEF.foundAsmStmt()) {
639  S.Diag(St->getBeginLoc(), diag::warn_attribute_ignored_no_calls_in_stmt)
640  << A;
641  return nullptr;
642  }
643 
644  return ::new (S.Context) NoMergeAttr(S.Context, A);
645 }
646 
647 template <typename OtherAttr, int DiagIdx>
648 static bool CheckStmtInlineAttr(Sema &SemaRef, const Stmt *OrigSt,
649  const Stmt *CurSt,
650  const AttributeCommonInfo &A) {
651  CallExprFinder OrigCEF(SemaRef, OrigSt);
652  CallExprFinder CEF(SemaRef, CurSt);
653 
654  // If the call expressions lists are equal in size, we can skip
655  // previously emitted diagnostics. However, if the statement has a pack
656  // expansion, we have no way of telling which CallExpr is the instantiated
657  // version of the other. In this case, we will end up re-diagnosing in the
658  // instantiation.
659  // ie: [[clang::always_inline]] non_dependent(), (other_call<Pack>()...)
660  // will diagnose nondependent again.
661  bool CanSuppressDiag =
662  OrigSt && CEF.getCallExprs().size() == OrigCEF.getCallExprs().size();
663 
664  if (!CEF.foundCallExpr()) {
665  return SemaRef.Diag(CurSt->getBeginLoc(),
666  diag::warn_attribute_ignored_no_calls_in_stmt)
667  << A;
668  }
669 
670  for (const auto &Tup :
671  llvm::zip_longest(OrigCEF.getCallExprs(), CEF.getCallExprs())) {
672  // If the original call expression already had a callee, we already
673  // diagnosed this, so skip it here. We can't skip if there isn't a 1:1
674  // relationship between the two lists of call expressions.
675  if (!CanSuppressDiag || !(*std::get<0>(Tup))->getCalleeDecl()) {
676  const Decl *Callee = (*std::get<1>(Tup))->getCalleeDecl();
677  if (Callee &&
678  (Callee->hasAttr<OtherAttr>() || Callee->hasAttr<FlattenAttr>())) {
679  SemaRef.Diag(CurSt->getBeginLoc(),
680  diag::warn_function_stmt_attribute_precedence)
681  << A << (Callee->hasAttr<OtherAttr>() ? DiagIdx : 1);
682  SemaRef.Diag(Callee->getBeginLoc(), diag::note_conflicting_attribute);
683  }
684  }
685  }
686 
687  return false;
688 }
689 
690 bool Sema::CheckNoInlineAttr(const Stmt *OrigSt, const Stmt *CurSt,
691  const AttributeCommonInfo &A) {
692  return CheckStmtInlineAttr<AlwaysInlineAttr, 0>(*this, OrigSt, CurSt, A);
693 }
694 
695 bool Sema::CheckAlwaysInlineAttr(const Stmt *OrigSt, const Stmt *CurSt,
696  const AttributeCommonInfo &A) {
697  return CheckStmtInlineAttr<NoInlineAttr, 2>(*this, OrigSt, CurSt, A);
698 }
699 
700 static Attr *handleNoInlineAttr(Sema &S, Stmt *St, const ParsedAttr &A,
701  SourceRange Range) {
702  NoInlineAttr NIA(S.Context, A);
703  if (!NIA.isStmtNoInline()) {
704  S.Diag(St->getBeginLoc(), diag::warn_function_attribute_ignored_in_stmt)
705  << "[[clang::noinline]]";
706  return nullptr;
707  }
708 
709  if (S.CheckNoInlineAttr(/*OrigSt=*/nullptr, St, A))
710  return nullptr;
711 
712  return ::new (S.Context) NoInlineAttr(S.Context, A);
713 }
714 
715 static Attr *handleAlwaysInlineAttr(Sema &S, Stmt *St, const ParsedAttr &A,
716  SourceRange Range) {
717  AlwaysInlineAttr AIA(S.Context, A);
718  if (!AIA.isClangAlwaysInline()) {
719  S.Diag(St->getBeginLoc(), diag::warn_function_attribute_ignored_in_stmt)
720  << "[[clang::always_inline]]";
721  return nullptr;
722  }
723 
724  if (S.CheckAlwaysInlineAttr(/*OrigSt=*/nullptr, St, A))
725  return nullptr;
726 
727  return ::new (S.Context) AlwaysInlineAttr(S.Context, A);
728 }
729 
730 static Attr *handleCXXAssumeAttr(Sema &S, Stmt *St, const ParsedAttr &A,
731  SourceRange Range) {
732  ExprResult Res = S.ActOnCXXAssumeAttr(St, A, Range);
733  if (!Res.isUsable())
734  return nullptr;
735 
736  return ::new (S.Context) CXXAssumeAttr(S.Context, A, Res.get());
737 }
738 
739 static Attr *handleMustTailAttr(Sema &S, Stmt *St, const ParsedAttr &A,
740  SourceRange Range) {
741  // Validation is in Sema::ActOnAttributedStmt().
742  return ::new (S.Context) MustTailAttr(S.Context, A);
743 }
744 
745 static Attr *handleLikely(Sema &S, Stmt *St, const ParsedAttr &A,
746  SourceRange Range) {
747 
748  if (!S.getLangOpts().CPlusPlus20 && A.isCXX11Attribute() && !A.getScopeName())
749  S.Diag(A.getLoc(), diag::ext_cxx20_attr) << A << Range;
750 
751  return ::new (S.Context) LikelyAttr(S.Context, A);
752 }
753 
754 static Attr *handleUnlikely(Sema &S, Stmt *St, const ParsedAttr &A,
755  SourceRange Range) {
756 
757  if (!S.getLangOpts().CPlusPlus20 && A.isCXX11Attribute() && !A.getScopeName())
758  S.Diag(A.getLoc(), diag::ext_cxx20_attr) << A << Range;
759 
760  return ::new (S.Context) UnlikelyAttr(S.Context, A);
761 }
762 
764  Expr *E) {
765  if (!E->isValueDependent()) {
766  llvm::APSInt ArgVal;
767  ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal);
768  if (Res.isInvalid())
769  return nullptr;
770  E = Res.get();
771 
772  // This attribute requires an integer argument which is a constant power of
773  // two between 1 and 4096 inclusive.
774  if (ArgVal < CodeAlignAttr::MinimumAlignment ||
775  ArgVal > CodeAlignAttr::MaximumAlignment || !ArgVal.isPowerOf2()) {
776  if (std::optional<int64_t> Value = ArgVal.trySExtValue())
777  Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
778  << CI << CodeAlignAttr::MinimumAlignment
779  << CodeAlignAttr::MaximumAlignment << Value.value();
780  else
781  Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
782  << CI << CodeAlignAttr::MinimumAlignment
783  << CodeAlignAttr::MaximumAlignment << E;
784  return nullptr;
785  }
786  }
787  return new (Context) CodeAlignAttr(Context, CI, E);
788 }
789 
790 static Attr *handleCodeAlignAttr(Sema &S, Stmt *St, const ParsedAttr &A) {
791 
792  Expr *E = A.getArgAsExpr(0);
793  return S.BuildCodeAlignAttr(A, E);
794 }
795 
796 // Diagnose non-identical duplicates as a 'conflicting' loop attributes
797 // and suppress duplicate errors in cases where the two match.
798 template <typename LoopAttrT>
800  auto FindFunc = [](const Attr *A) { return isa<const LoopAttrT>(A); };
801  const auto *FirstItr = std::find_if(Attrs.begin(), Attrs.end(), FindFunc);
802 
803  if (FirstItr == Attrs.end()) // no attributes found
804  return;
805 
806  const auto *LastFoundItr = FirstItr;
807  std::optional<llvm::APSInt> FirstValue;
808 
809  const auto *CAFA =
810  dyn_cast<ConstantExpr>(cast<LoopAttrT>(*FirstItr)->getAlignment());
811  // Return early if first alignment expression is dependent (since we don't
812  // know what the effective size will be), and skip the loop entirely.
813  if (!CAFA)
814  return;
815 
816  while (Attrs.end() != (LastFoundItr = std::find_if(LastFoundItr + 1,
817  Attrs.end(), FindFunc))) {
818  const auto *CASA =
819  dyn_cast<ConstantExpr>(cast<LoopAttrT>(*LastFoundItr)->getAlignment());
820  // If the value is dependent, we can not test anything.
821  if (!CASA)
822  return;
823  // Test the attribute values.
824  llvm::APSInt SecondValue = CASA->getResultAsAPSInt();
825  if (!FirstValue)
826  FirstValue = CAFA->getResultAsAPSInt();
827 
828  if (FirstValue != SecondValue) {
829  S.Diag((*LastFoundItr)->getLocation(), diag::err_loop_attr_conflict)
830  << *FirstItr;
831  S.Diag((*FirstItr)->getLocation(), diag::note_previous_attribute);
832  }
833  }
834  return;
835 }
836 
837 static Attr *handleMSConstexprAttr(Sema &S, Stmt *St, const ParsedAttr &A,
838  SourceRange Range) {
840  S.Diag(A.getLoc(), diag::warn_unknown_attribute_ignored)
841  << A << A.getRange();
842  return nullptr;
843  }
844  return ::new (S.Context) MSConstexprAttr(S.Context, A);
845 }
846 
847 #define WANT_STMT_MERGE_LOGIC
848 #include "clang/Sema/AttrParsedAttrImpl.inc"
849 #undef WANT_STMT_MERGE_LOGIC
850 
851 static void
853  const SmallVectorImpl<const Attr *> &Attrs) {
854  // The vast majority of attributed statements will only have one attribute
855  // on them, so skip all of the checking in the common case.
856  if (Attrs.size() < 2)
857  return;
858 
859  // First, check for the easy cases that are table-generated for us.
860  if (!DiagnoseMutualExclusions(S, Attrs))
861  return;
862 
863  enum CategoryType {
864  // For the following categories, they come in two variants: a state form and
865  // a numeric form. The state form may be one of default, enable, and
866  // disable. The numeric form provides an integer hint (for example, unroll
867  // count) to the transformer.
868  Vectorize,
869  Interleave,
870  UnrollAndJam,
871  Pipeline,
872  // For unroll, default indicates full unrolling rather than enabling the
873  // transformation.
874  Unroll,
875  // The loop distribution transformation only has a state form that is
876  // exposed by #pragma clang loop distribute (enable | disable).
877  Distribute,
878  // The vector predication only has a state form that is exposed by
879  // #pragma clang loop vectorize_predicate (enable | disable).
880  VectorizePredicate,
881  // This serves as a indicator to how many category are listed in this enum.
882  NumberOfCategories
883  };
884  // The following array accumulates the hints encountered while iterating
885  // through the attributes to check for compatibility.
886  struct {
887  const LoopHintAttr *StateAttr;
888  const LoopHintAttr *NumericAttr;
889  } HintAttrs[CategoryType::NumberOfCategories] = {};
890 
891  for (const auto *I : Attrs) {
892  const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I);
893 
894  // Skip non loop hint attributes
895  if (!LH)
896  continue;
897 
898  CategoryType Category = CategoryType::NumberOfCategories;
899  LoopHintAttr::OptionType Option = LH->getOption();
900  switch (Option) {
901  case LoopHintAttr::Vectorize:
902  case LoopHintAttr::VectorizeWidth:
903  Category = Vectorize;
904  break;
905  case LoopHintAttr::Interleave:
906  case LoopHintAttr::InterleaveCount:
907  Category = Interleave;
908  break;
909  case LoopHintAttr::Unroll:
910  case LoopHintAttr::UnrollCount:
911  Category = Unroll;
912  break;
913  case LoopHintAttr::UnrollAndJam:
914  case LoopHintAttr::UnrollAndJamCount:
915  Category = UnrollAndJam;
916  break;
917  case LoopHintAttr::Distribute:
918  // Perform the check for duplicated 'distribute' hints.
919  Category = Distribute;
920  break;
921  case LoopHintAttr::PipelineDisabled:
922  case LoopHintAttr::PipelineInitiationInterval:
923  Category = Pipeline;
924  break;
925  case LoopHintAttr::VectorizePredicate:
926  Category = VectorizePredicate;
927  break;
928  };
929 
930  assert(Category != NumberOfCategories && "Unhandled loop hint option");
931  auto &CategoryState = HintAttrs[Category];
932  const LoopHintAttr *PrevAttr;
933  if (Option == LoopHintAttr::Vectorize ||
934  Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll ||
935  Option == LoopHintAttr::UnrollAndJam ||
936  Option == LoopHintAttr::VectorizePredicate ||
937  Option == LoopHintAttr::PipelineDisabled ||
938  Option == LoopHintAttr::Distribute) {
939  // Enable|Disable|AssumeSafety hint. For example, vectorize(enable).
940  PrevAttr = CategoryState.StateAttr;
941  CategoryState.StateAttr = LH;
942  } else {
943  // Numeric hint. For example, vectorize_width(8).
944  PrevAttr = CategoryState.NumericAttr;
945  CategoryState.NumericAttr = LH;
946  }
947 
948  PrintingPolicy Policy(S.Context.getLangOpts());
949  SourceLocation OptionLoc = LH->getRange().getBegin();
950  if (PrevAttr)
951  // Cannot specify same type of attribute twice.
952  S.Diag(OptionLoc, diag::err_pragma_loop_compatibility)
953  << /*Duplicate=*/true << PrevAttr->getDiagnosticName(Policy)
954  << LH->getDiagnosticName(Policy);
955 
956  if (CategoryState.StateAttr && CategoryState.NumericAttr &&
957  (Category == Unroll || Category == UnrollAndJam ||
958  CategoryState.StateAttr->getState() == LoopHintAttr::Disable)) {
959  // Disable hints are not compatible with numeric hints of the same
960  // category. As a special case, numeric unroll hints are also not
961  // compatible with enable or full form of the unroll pragma because these
962  // directives indicate full unrolling.
963  S.Diag(OptionLoc, diag::err_pragma_loop_compatibility)
964  << /*Duplicate=*/false
965  << CategoryState.StateAttr->getDiagnosticName(Policy)
966  << CategoryState.NumericAttr->getDiagnosticName(Policy);
967  }
968  }
969 }
970 
971 template <typename LoopAttrT>
972 static void
974  const SmallVectorImpl<const Attr *> &Attrs,
975  bool isIntelFPGAAttr = true) {
976  const LoopAttrT *LoopAttr = nullptr;
977 
978  for (const auto *I : Attrs) {
979  if (LoopAttr && isa<LoopAttrT>(I)) {
980  // Cannot specify same type of attribute twice.
981  S.Diag(I->getLocation(), diag::err_sycl_loop_attr_duplication)
982  << isIntelFPGAAttr << LoopAttr;
983  }
984  if (isa<LoopAttrT>(I))
985  LoopAttr = cast<LoopAttrT>(I);
986  }
987 }
988 
989 // Diagnose non-identical duplicates as a 'conflicting' loop attributes
990 // and suppress duplicate errors in cases where the two match for
991 // FPGA attributes: 'SYCLIntelMaxInterleavingAttr',
992 // 'SYCLIntelSpeculatedIterationsAttr', 'SYCLIntelMaxReinvocationDelayAttr',
993 // 'SYCLIntelInitiationIntervalAttr', and 'SYCLIntelMaxConcurrencyAttr'
994 template <typename LoopAttrT>
996  auto FindFunc = [](const Attr *A) { return isa<const LoopAttrT>(A); };
997  const auto *FirstItr = std::find_if(Attrs.begin(), Attrs.end(), FindFunc);
998 
999  if (FirstItr == Attrs.end()) // no attributes found
1000  return;
1001 
1002  const auto *LastFoundItr = FirstItr;
1003  std::optional<llvm::APSInt> FirstValue;
1004 
1005  const auto *CAFA =
1006  dyn_cast<ConstantExpr>(cast<LoopAttrT>(*FirstItr)->getNExpr());
1007  // Return early if first expression is dependent (since we don't
1008  // know what the effective size will be), and skip the loop entirely.
1009  if (!CAFA)
1010  return;
1011 
1012  while (Attrs.end() != (LastFoundItr = std::find_if(LastFoundItr + 1,
1013  Attrs.end(), FindFunc))) {
1014  const auto *CASA =
1015  dyn_cast<ConstantExpr>(cast<LoopAttrT>(*LastFoundItr)->getNExpr());
1016  // If the value is dependent, we can not test anything.
1017  if (!CASA)
1018  return;
1019  // Test the attribute values.
1020  llvm::APSInt SecondValue = CASA->getResultAsAPSInt();
1021  if (!FirstValue)
1022  FirstValue = CAFA->getResultAsAPSInt();
1023 
1024  if (FirstValue != SecondValue) {
1025  S.Diag((*LastFoundItr)->getLocation(), diag::err_loop_attr_conflict)
1026  << *FirstItr;
1027  S.Diag((*FirstItr)->getLocation(), diag::note_previous_attribute);
1028  return;
1029  }
1030  }
1031 }
1032 
1034  Sema &S, const SmallVectorImpl<const Attr *> &Attrs) {
1035  CheckForDuplicateAttrs<SYCLIntelInitiationIntervalAttr>(S, Attrs);
1036  CheckForDuplicateAttrs<SYCLIntelMaxConcurrencyAttr>(S, Attrs);
1037  CheckForDuplicationSYCLLoopAttribute<SYCLIntelLoopCoalesceAttr>(S, Attrs);
1038  CheckForDuplicationSYCLLoopAttribute<SYCLIntelDisableLoopPipeliningAttr>(
1039  S, Attrs);
1040  CheckForDuplicateAttrs<SYCLIntelMaxInterleavingAttr>(S, Attrs);
1041  CheckForDuplicateAttrs<SYCLIntelSpeculatedIterationsAttr>(S, Attrs);
1043  CheckForDuplicationSYCLLoopAttribute<LoopUnrollHintAttr>(S, Attrs, false);
1045  CheckForDuplicationSYCLLoopAttribute<SYCLIntelNofusionAttr>(S, Attrs);
1046  CheckForDuplicateAttrs<SYCLIntelMaxReinvocationDelayAttr>(S, Attrs);
1047  CheckForDuplicationSYCLLoopAttribute<SYCLIntelEnableLoopPipeliningAttr>(
1048  S, Attrs);
1049 }
1050 
1052  Sema &S, const SmallVectorImpl<const Attr *> &Attrs, SourceRange Range) {
1053 
1054  // This check is entered after it was analyzed that there are no duplicating
1055  // pragmas and loop attributes. So, let's perform check that there are no
1056  // conflicting pragma unroll and unroll attribute for the loop.
1057  const LoopUnrollHintAttr *AttrUnroll = nullptr;
1058  const LoopHintAttr *PragmaUnroll = nullptr;
1059  for (const auto *I : Attrs) {
1060  if (auto *LH = dyn_cast<LoopUnrollHintAttr>(I))
1061  AttrUnroll = LH;
1062  if (auto *LH = dyn_cast<LoopHintAttr>(I)) {
1063  LoopHintAttr::OptionType Opt = LH->getOption();
1064  if (Opt == LoopHintAttr::Unroll || Opt == LoopHintAttr::UnrollCount)
1065  PragmaUnroll = LH;
1066  }
1067  }
1068 
1069  if (AttrUnroll && PragmaUnroll) {
1070  PrintingPolicy Policy(S.Context.getLangOpts());
1072  S.Diag(Loc, diag::err_loop_unroll_compatibility)
1073  << PragmaUnroll->getDiagnosticName(Policy)
1074  << AttrUnroll->getDiagnosticName(Policy);
1075  }
1076 }
1077 
1078 static bool CheckLoopUnrollAttrExpr(Sema &S, Expr *E,
1079  const AttributeCommonInfo &A,
1080  unsigned *UnrollFactor = nullptr) {
1081  if (E && !E->isInstantiationDependent()) {
1082  std::optional<llvm::APSInt> ArgVal = E->getIntegerConstantExpr(S.Context);
1083  if (!ArgVal)
1084  return S.Diag(E->getExprLoc(), diag::err_attribute_argument_type)
1086  << E->getSourceRange();
1087 
1088  if (ArgVal->isNonPositive())
1089  return S.Diag(E->getExprLoc(),
1090  diag::err_attribute_requires_positive_integer)
1091  << A.getAttrName() << /* positive */ 0;
1092 
1093  if (UnrollFactor)
1094  *UnrollFactor = ArgVal->getZExtValue();
1095  }
1096  return false;
1097 }
1098 
1100  Expr *E) {
1101  return !CheckLoopUnrollAttrExpr(*this, E, A)
1102  ? new (Context) LoopUnrollHintAttr(Context, A, E)
1103  : nullptr;
1104 }
1105 
1106 OpenCLUnrollHintAttr *
1108  unsigned UnrollFactor = 0;
1109  return !CheckLoopUnrollAttrExpr(*this, E, A, &UnrollFactor)
1110  ? new (Context) OpenCLUnrollHintAttr(Context, A, UnrollFactor)
1111  : nullptr;
1112 }
1113 
1114 static Attr *handleLoopUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A,
1115  SourceRange Range) {
1116  // Although the feature was introduced only in OpenCL C v2.0 s6.11.5, it's
1117  // useful for OpenCL 1.x too and doesn't require HW support.
1118  // opencl_unroll_hint or clang::unroll can have 0 arguments (compiler
1119  // determines unrolling factor) or 1 argument (the unroll factor provided
1120  // by the user).
1121 
1122  Expr *E = A.getNumArgs() ? A.getArgAsExpr(0) : nullptr;
1123  if (A.getParsedKind() == ParsedAttr::AT_OpenCLUnrollHint)
1124  return S.BuildOpenCLLoopUnrollHintAttr(A, E);
1125  if (A.getParsedKind() == ParsedAttr::AT_LoopUnrollHint)
1126  return S.BuildLoopUnrollHintAttr(A, E);
1127 
1128  llvm_unreachable("Unknown loop unroll hint");
1129 }
1130 
1131 static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
1132  SourceRange Range) {
1134  return nullptr;
1135 
1136  // Unknown attributes are automatically warned on. Target-specific attributes
1137  // which do not apply to the current target architecture are treated as
1138  // though they were unknown attributes.
1139  const TargetInfo *Aux = S.Context.getAuxTargetInfo();
1142  (S.Context.getLangOpts().SYCLIsDevice && Aux &&
1143  A.existsInTarget(*Aux)))) {
1145  ? (unsigned)diag::err_keyword_not_supported_on_target
1146  : A.isDeclspecAttribute()
1147  ? (unsigned)diag::warn_unhandled_ms_attribute_ignored
1148  : (unsigned)diag::warn_unknown_attribute_ignored)
1149  << A << A.getRange();
1150  return nullptr;
1151  }
1152 
1153  if (S.checkCommonAttributeFeatures(St, A))
1154  return nullptr;
1155 
1156  switch (A.getKind()) {
1157  case ParsedAttr::AT_AlwaysInline:
1158  return handleAlwaysInlineAttr(S, St, A, Range);
1159  case ParsedAttr::AT_CXXAssume:
1160  return handleCXXAssumeAttr(S, St, A, Range);
1161  case ParsedAttr::AT_FallThrough:
1162  return handleFallThroughAttr(S, St, A, Range);
1163  case ParsedAttr::AT_LoopHint:
1164  return handleLoopHintAttr(S, St, A, Range);
1165  case ParsedAttr::AT_SYCLIntelIVDep:
1166  return handleIntelIVDepAttr(S, St, A);
1167  case ParsedAttr::AT_SYCLIntelInitiationInterval:
1168  return handleSYCLIntelInitiationIntervalAttr(S, St, A);
1169  case ParsedAttr::AT_SYCLIntelMaxConcurrency:
1170  return handleSYCLIntelMaxConcurrencyAttr(S, St, A);
1171  case ParsedAttr::AT_SYCLIntelLoopCoalesce:
1172  return handleSYCLIntelLoopCoalesceAttr(S, St, A);
1173  case ParsedAttr::AT_SYCLIntelDisableLoopPipelining:
1175  case ParsedAttr::AT_SYCLIntelMaxInterleaving:
1176  return handleSYCLIntelMaxInterleavingAttr(S, St, A);
1177  case ParsedAttr::AT_SYCLIntelSpeculatedIterations:
1178  return handleSYCLIntelSpeculatedIterationsAttr(S, St, A);
1179  case ParsedAttr::AT_SYCLIntelLoopCount:
1180  return handleSYCLIntelLoopCountAttr(S, St, A);
1181  case ParsedAttr::AT_OpenCLUnrollHint:
1182  case ParsedAttr::AT_LoopUnrollHint:
1183  return handleLoopUnrollHint(S, St, A, Range);
1184  case ParsedAttr::AT_Suppress:
1185  return handleSuppressAttr(S, St, A, Range);
1186  case ParsedAttr::AT_NoMerge:
1187  return handleNoMergeAttr(S, St, A, Range);
1188  case ParsedAttr::AT_NoInline:
1189  return handleNoInlineAttr(S, St, A, Range);
1190  case ParsedAttr::AT_MustTail:
1191  return handleMustTailAttr(S, St, A, Range);
1192  case ParsedAttr::AT_Likely:
1193  return handleLikely(S, St, A, Range);
1194  case ParsedAttr::AT_Unlikely:
1195  return handleUnlikely(S, St, A, Range);
1196  case ParsedAttr::AT_SYCLIntelNofusion:
1197  return handleIntelNofusionAttr(S, St, A);
1198  case ParsedAttr::AT_SYCLIntelMaxReinvocationDelay:
1199  return handleSYCLIntelMaxReinvocationDelayAttr(S, St, A);
1200  case ParsedAttr::AT_SYCLIntelEnableLoopPipelining:
1201  return handleSYCLIntelEnableLoopPipeliningAttr(S, St, A);
1202  case ParsedAttr::AT_CodeAlign:
1203  return handleCodeAlignAttr(S, St, A);
1204  case ParsedAttr::AT_MSConstexpr:
1205  return handleMSConstexprAttr(S, St, A, Range);
1206  default:
1207  // N.B., ClangAttrEmitter.cpp emits a diagnostic helper that ensures a
1208  // declaration attribute is not written on a statement, but this code is
1209  // needed for attributes in Attr.td that do not list any subjects.
1210  S.Diag(A.getRange().getBegin(), diag::err_decl_attribute_invalid_on_stmt)
1211  << A << A.isRegularKeywordAttribute() << St->getBeginLoc();
1212  return nullptr;
1213  }
1214 }
1215 
1217  SmallVectorImpl<const Attr *> &OutAttrs) {
1218  for (const ParsedAttr &AL : InAttrs) {
1219  if (const Attr *A = ProcessStmtAttribute(*this, S, AL, InAttrs.Range))
1220  OutAttrs.push_back(A);
1221  }
1222 
1223  CheckForIncompatibleAttributes(*this, OutAttrs);
1224  CheckForIncompatibleSYCLLoopAttributes(*this, OutAttrs);
1225  CheckForIncompatibleUnrollHintAttributes(*this, OutAttrs, InAttrs.Range);
1226  CheckForDuplicateLoopAttrs<CodeAlignAttr>(*this, OutAttrs);
1227 }
1228 
1230  CheckRedundantSYCLIntelIVDepAttrs(*this, Attrs);
1231  CheckForDuplicateAttrs<SYCLIntelSpeculatedIterationsAttr>(*this, Attrs);
1232  CheckForDuplicateAttrs<SYCLIntelMaxInterleavingAttr>(*this, Attrs);
1233  CheckForDuplicateAttrs<SYCLIntelMaxReinvocationDelayAttr>(*this, Attrs);
1234  CheckForDuplicateAttrs<SYCLIntelInitiationIntervalAttr>(*this, Attrs);
1235  CheckForDuplicateAttrs<SYCLIntelMaxConcurrencyAttr>(*this, Attrs);
1236  return false;
1237 }
1238 
1240  CheckForDuplicateLoopAttrs<CodeAlignAttr>(*this, Attrs);
1241  return false;
1242 }
1243 
1245  SourceRange Range) {
1246  if (A.getNumArgs() != 1 || !A.getArgAsExpr(0)) {
1247  Diag(A.getLoc(), diag::err_attribute_wrong_number_arguments)
1248  << A.getAttrName() << 1 << Range;
1249  return ExprError();
1250  }
1251 
1252  auto *Assumption = A.getArgAsExpr(0);
1253 
1254  if (DiagnoseUnexpandedParameterPack(Assumption)) {
1255  return ExprError();
1256  }
1257 
1258  if (Assumption->getDependence() == ExprDependence::None) {
1259  ExprResult Res = BuildCXXAssumeExpr(Assumption, A.getAttrName(), Range);
1260  if (Res.isInvalid())
1261  return ExprError();
1262  Assumption = Res.get();
1263  }
1264 
1265  if (!getLangOpts().CPlusPlus23 &&
1267  Diag(A.getLoc(), diag::ext_cxx23_attr) << A << Range;
1268 
1269  return Assumption;
1270 }
1271 
1273  const IdentifierInfo *AttrName,
1274  SourceRange Range) {
1275  ExprResult Res = CorrectDelayedTyposInExpr(Assumption);
1276  if (Res.isInvalid())
1277  return ExprError();
1278 
1279  Res = CheckPlaceholderExpr(Res.get());
1280  if (Res.isInvalid())
1281  return ExprError();
1282 
1283  Res = PerformContextuallyConvertToBool(Res.get());
1284  if (Res.isInvalid())
1285  return ExprError();
1286 
1287  Assumption = Res.get();
1288  if (Assumption->HasSideEffects(Context))
1289  Diag(Assumption->getBeginLoc(), diag::warn_assume_side_effects)
1290  << AttrName << Range;
1291 
1292  return Assumption;
1293 }
Defines the clang::ASTContext interface.
llvm::APSInt APSInt
Defines the classes clang::DelayedDiagnostic and clang::AccessedEntity.
int Category
Definition: Format.cpp:2979
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
SourceRange Range
Definition: SemaObjC.cpp:754
SourceLocation Loc
Definition: SemaObjC.cpp:755
static Attr * handleUnlikely(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range)
static void CheckForDuplicateLoopAttrs(Sema &S, ArrayRef< const Attr * > Attrs)
static Attr * handleSuppressAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range)
static IVDepExprResult HandleIVDepAttrExpr(Sema &S, Expr *E, unsigned &SafelenValue)
static Attr * handleSYCLIntelMaxInterleavingAttr(Sema &S, Stmt *St, const ParsedAttr &A)
static Attr * handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange)
static Attr * handleSYCLIntelInitiationIntervalAttr(Sema &S, Stmt *St, const ParsedAttr &A)
static bool CheckLoopUnrollAttrExpr(Sema &S, Expr *E, const AttributeCommonInfo &A, unsigned *UnrollFactor=nullptr)
static Attr * handleSYCLIntelLoopCoalesceAttr(Sema &S, Stmt *St, const ParsedAttr &A)
static void CheckForIncompatibleSYCLLoopAttributes(Sema &S, const SmallVectorImpl< const Attr * > &Attrs)
static Attr * handleMustTailAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range)
static Attr * handleMSConstexprAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range)
static Attr * ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range)
static Attr * handleSYCLIntelMaxConcurrencyAttr(Sema &S, Stmt *St, const ParsedAttr &A)
static void CheckForDuplicateSYCLIntelLoopCountAttrs(Sema &S, ArrayRef< const Attr * > Attrs)
static Attr * handleIntelNofusionAttr(Sema &S, Stmt *St, const ParsedAttr &A)
static void CheckForDuplicateAttrs(Sema &S, ArrayRef< const Attr * > Attrs)
static Attr * handleSYCLIntelEnableLoopPipeliningAttr(Sema &S, Stmt *, const ParsedAttr &A)
static Attr * handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range)
static void CheckForDuplicationSYCLLoopAttribute(Sema &S, const SmallVectorImpl< const Attr * > &Attrs, bool isIntelFPGAAttr=true)
static Attr * handleAlwaysInlineAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range)
static Attr * handleSYCLIntelLoopCountAttr(Sema &S, Stmt *St, const ParsedAttr &A)
static void FilterAttributeList(ArrayRef< const Attr * > Attrs, SmallVectorImpl< const T * > &FilteredAttrs)
static Attr * handleCXXAssumeAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range)
static Attr * handleSYCLIntelDisableLoopPipeliningAttr(Sema &S, Stmt *, const ParsedAttr &A)
static Attr * handleCodeAlignAttr(Sema &S, Stmt *St, const ParsedAttr &A)
static Attr * handleSYCLIntelMaxReinvocationDelayAttr(Sema &S, Stmt *St, const ParsedAttr &A)
static Attr * handleNoMergeAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range)
IVDepExprResult
static void CheckForIncompatibleAttributes(Sema &S, const SmallVectorImpl< const Attr * > &Attrs)
static Attr * handleSYCLIntelSpeculatedIterationsAttr(Sema &S, Stmt *St, const ParsedAttr &A)
static Attr * handleNoInlineAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range)
static bool CheckStmtInlineAttr(Sema &SemaRef, const Stmt *OrigSt, const Stmt *CurSt, const AttributeCommonInfo &A)
void CheckForIncompatibleUnrollHintAttributes(Sema &S, const SmallVectorImpl< const Attr * > &Attrs, SourceRange Range)
static Attr * handleIntelIVDepAttr(Sema &S, Stmt *St, const ParsedAttr &A)
static Attr * handleLikely(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range)
static void CheckRedundantSYCLIntelIVDepAttrs(Sema &S, ArrayRef< const Attr * > Attrs)
static bool checkSYCLIntelIVDepSafeLen(Sema &S, llvm::APSInt &Value, Expr *E)
static Attr * handleLoopUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range)
Defines the SourceManager interface.
LineState State
const LangOptions & getLangOpts() const
Definition: ASTContext.h:778
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:760
const TargetInfo * getAuxTargetInfo() const
Definition: ASTContext.h:761
PtrTy get() const
Definition: Ownership.h:170
bool isInvalid() const
Definition: Ownership.h:166
bool isUsable() const
Definition: Ownership.h:168
AsmStmt is the base class for GCCAsmStmt and MSAsmStmt.
Definition: Stmt.h:3100
Attr - This represents one attribute.
Definition: Attr.h:46
SourceLocation getLocation() const
Definition: Attr.h:99
unsigned getAttributeSpellingListIndex() const
const IdentifierInfo * getAttrName() const
SourceLocation getLoc() const
const IdentifierInfo * getScopeName() const
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2872
ConstEvaluatedExprVisitor - This class visits 'const Expr *'s.
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1282
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
This represents one expression.
Definition: Expr.h:110
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition: Expr.h:175
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
Definition: Expr.cpp:3608
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition: Expr.h:221
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:277
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
QualType getType() const
Definition: Expr.h:142
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
Definition: Diagnostic.h:98
One of these records is kept for each identifier that is lexed.
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
StringRef getName() const
Return the actual identifier string.
bool isCompatibleWithMSVC(MSVCMajorVersion MajorVersion) const
Definition: LangOptions.h:666
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:129
IdentifierLoc * getArgAsIdent(unsigned Arg) const
Definition: ParsedAttr.h:406
bool existsInTarget(const TargetInfo &Target) const
Definition: ParsedAttr.cpp:201
Expr * getArgAsExpr(unsigned Arg) const
Definition: ParsedAttr.h:398
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
Definition: ParsedAttr.h:386
AttributeCommonInfo::Kind getKind() const
Definition: ParsedAttr.h:632
bool isArgExpr(unsigned Arg) const
Definition: ParsedAttr.h:394
bool isInvalid() const
Definition: ParsedAttr.h:359
ParsedAttributes - A collection of parsed attributes.
Definition: ParsedAttr.h:963
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:57
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:462
void ProcessStmtAttributes(Stmt *Stmt, const ParsedAttributes &InAttrs, SmallVectorImpl< const Attr * > &OutAttrs)
Process the attributes before creating an attributed statement.
bool checkCommonAttributeFeatures(const Decl *D, const ParsedAttr &A, bool SkipArgCountCheck=false)
Handles semantic checking for features that are common to all attributes, such as checking whether a ...
Definition: SemaAttr.cpp:1454
ExprResult BuildCXXAssumeExpr(Expr *Assumption, const IdentifierInfo *AttrName, SourceRange Range)
SYCLIntelInitiationIntervalAttr * BuildSYCLIntelInitiationIntervalAttr(const AttributeCommonInfo &CI, Expr *E)
LoopUnrollHintAttr * BuildLoopUnrollHintAttr(const AttributeCommonInfo &A, Expr *E)
SYCLIntelMaxConcurrencyAttr * BuildSYCLIntelMaxConcurrencyAttr(const AttributeCommonInfo &CI, Expr *E)
OpenCLUnrollHintAttr * BuildOpenCLLoopUnrollHintAttr(const AttributeCommonInfo &A, Expr *E)
ASTContext & Context
Definition: Sema.h:857
SYCLIntelSpeculatedIterationsAttr * BuildSYCLIntelSpeculatedIterationsAttr(const AttributeCommonInfo &CI, Expr *E)
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)
Calls Lexer::getLocForEndOfToken()
Definition: Sema.cpp:68
void CheckDeprecatedSYCLAttributeSpelling(const ParsedAttr &A, StringRef NewName="")
Diagnoses an attribute in the 'intelfpga' namespace and suggests using the attribute in the 'intel' n...
const LangOptions & getLangOpts() const
Definition: Sema.h:519
SYCLIntelMaxReinvocationDelayAttr * BuildSYCLIntelMaxReinvocationDelayAttr(const AttributeCommonInfo &CI, Expr *E)
SYCLIntelMaxInterleavingAttr * BuildSYCLIntelMaxInterleavingAttr(const AttributeCommonInfo &CI, Expr *E)
SYCLIntelIVDepAttr * BuildSYCLIntelIVDepAttr(const AttributeCommonInfo &CI, Expr *Expr1, Expr *Expr2)
SYCLIntelLoopCoalesceAttr * BuildSYCLIntelLoopCoalesceAttr(const AttributeCommonInfo &CI, Expr *E)
bool CheckLoopHintExpr(Expr *E, SourceLocation Loc, bool AllowZero)
Definition: SemaExpr.cpp:3756
bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, const Expr *E, StringRef &Str, SourceLocation *ArgLocation=nullptr)
bool CheckRebuiltStmtAttributes(ArrayRef< const Attr * > Attrs)
bool CheckNoInlineAttr(const Stmt *OrigSt, const Stmt *CurSt, const AttributeCommonInfo &A)
bool CheckRebuiltAttributedStmtAttributes(ArrayRef< const Attr * > Attrs)
bool CheckAlwaysInlineAttr(const Stmt *OrigSt, const Stmt *CurSt, const AttributeCommonInfo &A)
ExprResult ActOnCXXAssumeAttr(Stmt *St, const ParsedAttr &A, SourceRange Range)
ASTContext & getASTContext() const
Definition: Sema.h:526
CodeAlignAttr * BuildCodeAlignAttr(const AttributeCommonInfo &CI, Expr *E)
sema::FunctionScopeInfo * getCurFunction() const
Definition: Sema.h:891
DeclContext * getCurLexicalContext() const
Definition: Sema.h:701
SYCLIntelLoopCountAttr * BuildSYCLIntelLoopCountAttr(const AttributeCommonInfo &CI, Expr *E)
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
RetTy Visit(PTR(Stmt) S, ParamTys... P)
Definition: StmtVisitor.h:44
Stmt - This represents one statement.
Definition: Stmt.h:84
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:326
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:338
Exposes information about the current target.
Definition: TargetInfo.h:218
bool isArrayType() const
Definition: Type.h:7690
bool isPointerType() const
Definition: Type.h:7624
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:707
Defines the clang::TargetInfo interface.
constexpr XRayInstrMask None
Definition: XRayInstr.h:38
bool Cast(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1717
ASTEdit remove(RangeSelector S)
Removes the source selected by S.
The JSON file list parser is used to communicate input to InstallAPI.
@ CPlusPlus23
Definition: LangStandard.h:60
@ AANT_ArgumentIntegerConstant
Definition: ParsedAttr.h:1086
ExprResult ExprError()
Definition: Ownership.h:264
const FunctionProtoType * T
@ Other
Other implicit parameter.
Wraps an identifier and optional source location for the identifier.
Definition: ParsedAttr.h:103
IdentifierInfo * Ident
Definition: ParsedAttr.h:105
Describes how types, statements, expressions, and declarations should be printed.
Definition: PrettyPrinter.h:57