16
16
#include " clang/Basic/DiagnosticSema.h"
17
17
#include " clang/Basic/OpenACCKinds.h"
18
18
#include " clang/Sema/Sema.h"
19
+ #include " llvm/ADT/StringExtras.h"
19
20
#include " llvm/Support/Casting.h"
20
21
21
22
using namespace clang ;
@@ -367,14 +368,26 @@ ExprResult SemaOpenACC::ActOnIntExpr(OpenACCDirectiveKind DK,
367
368
assert (((DK != OpenACCDirectiveKind::Invalid &&
368
369
CK == OpenACCClauseKind::Invalid) ||
369
370
(DK == OpenACCDirectiveKind::Invalid &&
370
- CK != OpenACCClauseKind::Invalid)) &&
371
+ CK != OpenACCClauseKind::Invalid) ||
372
+ (DK == OpenACCDirectiveKind::Invalid &&
373
+ CK == OpenACCClauseKind::Invalid)) &&
371
374
" Only one of directive or clause kind should be provided" );
372
375
373
376
class IntExprConverter : public Sema ::ICEConvertDiagnoser {
374
377
OpenACCDirectiveKind DirectiveKind;
375
378
OpenACCClauseKind ClauseKind;
376
379
Expr *IntExpr;
377
380
381
+ // gets the index into the diagnostics so we can use this for clauses,
382
+ // directives, and sub array.s
383
+ unsigned getDiagKind () const {
384
+ if (ClauseKind != OpenACCClauseKind::Invalid)
385
+ return 0 ;
386
+ if (DirectiveKind != OpenACCDirectiveKind::Invalid)
387
+ return 1 ;
388
+ return 2 ;
389
+ }
390
+
378
391
public:
379
392
IntExprConverter (OpenACCDirectiveKind DK, OpenACCClauseKind CK,
380
393
Expr *IntExpr)
@@ -390,12 +403,8 @@ ExprResult SemaOpenACC::ActOnIntExpr(OpenACCDirectiveKind DK,
390
403
}
391
404
SemaBase::SemaDiagnosticBuilder diagnoseNotInt (Sema &S, SourceLocation Loc,
392
405
QualType T) override {
393
- if (ClauseKind != OpenACCClauseKind::Invalid)
394
- return S.Diag (Loc, diag::err_acc_int_expr_requires_integer) <<
395
- /* Clause=*/ 0 << ClauseKind << T;
396
-
397
- return S.Diag (Loc, diag::err_acc_int_expr_requires_integer) <<
398
- /* Directive=*/ 1 << DirectiveKind << T;
406
+ return S.Diag (Loc, diag::err_acc_int_expr_requires_integer)
407
+ << getDiagKind () << ClauseKind << DirectiveKind << T;
399
408
}
400
409
401
410
SemaBase::SemaDiagnosticBuilder
@@ -503,12 +512,211 @@ ExprResult SemaOpenACC::ActOnArraySectionExpr(Expr *Base, SourceLocation LBLoc,
503
512
SourceLocation RBLoc) {
504
513
ASTContext &Context = getASTContext ();
505
514
506
- // TODO OpenACC: We likely have to reproduce a lot of the same logic from the
507
- // OMP version of this, but at the moment we don't have a good way to test it,
508
- // so for now we'll just create the node.
515
+ // Handle placeholders.
516
+ if (Base->hasPlaceholderType () &&
517
+ !Base->hasPlaceholderType (BuiltinType::ArraySection)) {
518
+ ExprResult Result = SemaRef.CheckPlaceholderExpr (Base);
519
+ if (Result.isInvalid ())
520
+ return ExprError ();
521
+ Base = Result.get ();
522
+ }
523
+ if (LowerBound && LowerBound->getType ()->isNonOverloadPlaceholderType ()) {
524
+ ExprResult Result = SemaRef.CheckPlaceholderExpr (LowerBound);
525
+ if (Result.isInvalid ())
526
+ return ExprError ();
527
+ Result = SemaRef.DefaultLvalueConversion (Result.get ());
528
+ if (Result.isInvalid ())
529
+ return ExprError ();
530
+ LowerBound = Result.get ();
531
+ }
532
+ if (Length && Length->getType ()->isNonOverloadPlaceholderType ()) {
533
+ ExprResult Result = SemaRef.CheckPlaceholderExpr (Length);
534
+ if (Result.isInvalid ())
535
+ return ExprError ();
536
+ Result = SemaRef.DefaultLvalueConversion (Result.get ());
537
+ if (Result.isInvalid ())
538
+ return ExprError ();
539
+ Length = Result.get ();
540
+ }
541
+
542
+ // Check the 'base' value, it must be an array or pointer type, and not to/of
543
+ // a function type.
544
+ QualType OriginalBaseTy = ArraySectionExpr::getBaseOriginalType (Base);
545
+ QualType ResultTy;
546
+ if (!Base->isTypeDependent ()) {
547
+ if (OriginalBaseTy->isAnyPointerType ()) {
548
+ ResultTy = OriginalBaseTy->getPointeeType ();
549
+ } else if (OriginalBaseTy->isArrayType ()) {
550
+ ResultTy = OriginalBaseTy->getAsArrayTypeUnsafe ()->getElementType ();
551
+ } else {
552
+ return ExprError (
553
+ Diag (Base->getExprLoc (), diag::err_acc_typecheck_subarray_value)
554
+ << Base->getSourceRange ());
555
+ }
556
+
557
+ if (ResultTy->isFunctionType ()) {
558
+ Diag (Base->getExprLoc (), diag::err_acc_subarray_function_type)
559
+ << ResultTy << Base->getSourceRange ();
560
+ return ExprError ();
561
+ }
562
+
563
+ if (SemaRef.RequireCompleteType (Base->getExprLoc (), ResultTy,
564
+ diag::err_acc_subarray_incomplete_type,
565
+ Base))
566
+ return ExprError ();
567
+
568
+ if (!Base->hasPlaceholderType (BuiltinType::ArraySection)) {
569
+ ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion (Base);
570
+ if (Result.isInvalid ())
571
+ return ExprError ();
572
+ Base = Result.get ();
573
+ }
574
+ }
575
+
576
+ auto GetRecovery = [&](Expr *E, QualType Ty) {
577
+ ExprResult Recovery =
578
+ SemaRef.CreateRecoveryExpr (E->getBeginLoc (), E->getEndLoc (), E, Ty);
579
+ return Recovery.isUsable () ? Recovery.get () : nullptr ;
580
+ };
581
+
582
+ // Ensure both of the expressions are int-exprs.
583
+ if (LowerBound && !LowerBound->isTypeDependent ()) {
584
+ ExprResult LBRes =
585
+ ActOnIntExpr (OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Invalid,
586
+ LowerBound->getExprLoc (), LowerBound);
587
+
588
+ if (LBRes.isUsable ())
589
+ LBRes = SemaRef.DefaultLvalueConversion (LBRes.get ());
590
+ LowerBound =
591
+ LBRes.isUsable () ? LBRes.get () : GetRecovery (LowerBound, Context.IntTy );
592
+ }
593
+
594
+ if (Length && !Length->isTypeDependent ()) {
595
+ ExprResult LenRes =
596
+ ActOnIntExpr (OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Invalid,
597
+ Length->getExprLoc (), Length);
598
+
599
+ if (LenRes.isUsable ())
600
+ LenRes = SemaRef.DefaultLvalueConversion (LenRes.get ());
601
+ Length =
602
+ LenRes.isUsable () ? LenRes.get () : GetRecovery (Length, Context.IntTy );
603
+ }
604
+
605
+ // Length is required if the base type is not an array of known bounds.
606
+ if (!Length && (OriginalBaseTy.isNull () ||
607
+ (!OriginalBaseTy->isDependentType () &&
608
+ !OriginalBaseTy->isConstantArrayType () &&
609
+ !OriginalBaseTy->isDependentSizedArrayType ()))) {
610
+ bool IsArray = !OriginalBaseTy.isNull () && OriginalBaseTy->isArrayType ();
611
+ Diag (ColonLoc, diag::err_acc_subarray_no_length) << IsArray;
612
+ // Fill in a dummy 'length' so that when we instantiate this we don't
613
+ // double-diagnose here.
614
+ ExprResult Recovery = SemaRef.CreateRecoveryExpr (
615
+ ColonLoc, SourceLocation (), ArrayRef<Expr *>{std::nullopt},
616
+ Context.IntTy );
617
+ Length = Recovery.isUsable () ? Recovery.get () : nullptr ;
618
+ }
619
+
620
+ // Check the values of each of the arguments, they cannot be negative(we
621
+ // assume), and if the array bound is known, must be within range. As we do
622
+ // so, do our best to continue with evaluation, we can set the
623
+ // value/expression to nullptr/nullopt if they are invalid, and treat them as
624
+ // not present for the rest of evaluation.
625
+
626
+ // We don't have to check for dependence, because the dependent size is
627
+ // represented as a different AST node.
628
+ std::optional<llvm::APSInt> BaseSize;
629
+ if (!OriginalBaseTy.isNull () && OriginalBaseTy->isConstantArrayType ()) {
630
+ const auto *ArrayTy = Context.getAsConstantArrayType (OriginalBaseTy);
631
+ BaseSize = ArrayTy->getSize ();
632
+ }
633
+
634
+ auto GetBoundValue = [&](Expr *E) -> std::optional<llvm::APSInt> {
635
+ if (!E || E->isInstantiationDependent ())
636
+ return std::nullopt;
637
+
638
+ Expr::EvalResult Res;
639
+ if (!E->EvaluateAsInt (Res, Context))
640
+ return std::nullopt;
641
+ return Res.Val .getInt ();
642
+ };
643
+
644
+ std::optional<llvm::APSInt> LowerBoundValue = GetBoundValue (LowerBound);
645
+ std::optional<llvm::APSInt> LengthValue = GetBoundValue (Length);
646
+
647
+ // Check lower bound for negative or out of range.
648
+ if (LowerBoundValue.has_value ()) {
649
+ if (LowerBoundValue->isNegative ()) {
650
+ Diag (LowerBound->getExprLoc (), diag::err_acc_subarray_negative)
651
+ << /* LowerBound=*/ 0 << toString (*LowerBoundValue, /* Radix=*/ 10 );
652
+ LowerBoundValue.reset ();
653
+ LowerBound = GetRecovery (LowerBound, LowerBound->getType ());
654
+ } else if (BaseSize.has_value () &&
655
+ llvm::APSInt::compareValues (*LowerBoundValue, *BaseSize) >= 0 ) {
656
+ // Lower bound (start index) must be less than the size of the array.
657
+ Diag (LowerBound->getExprLoc (), diag::err_acc_subarray_out_of_range)
658
+ << /* LowerBound=*/ 0 << toString (*LowerBoundValue, /* Radix=*/ 10 )
659
+ << toString (*BaseSize, /* Radix=*/ 10 );
660
+ LowerBoundValue.reset ();
661
+ LowerBound = GetRecovery (LowerBound, LowerBound->getType ());
662
+ }
663
+ }
664
+
665
+ // Check length for negative or out of range.
666
+ if (LengthValue.has_value ()) {
667
+ if (LengthValue->isNegative ()) {
668
+ Diag (Length->getExprLoc (), diag::err_acc_subarray_negative)
669
+ << /* Length=*/ 1 << toString (*LengthValue, /* Radix=*/ 10 );
670
+ LengthValue.reset ();
671
+ Length = GetRecovery (Length, Length->getType ());
672
+ } else if (BaseSize.has_value () &&
673
+ llvm::APSInt::compareValues (*LengthValue, *BaseSize) > 0 ) {
674
+ // Length must be lessthan or EQUAL to the size of the array.
675
+ Diag (Length->getExprLoc (), diag::err_acc_subarray_out_of_range)
676
+ << /* Length=*/ 1 << toString (*LengthValue, /* Radix=*/ 10 )
677
+ << toString (*BaseSize, /* Radix=*/ 10 );
678
+ LengthValue.reset ();
679
+ Length = GetRecovery (Length, Length->getType ());
680
+ }
681
+ }
682
+
683
+ // Adding two APSInts requires matching sign, so extract that here.
684
+ auto AddAPSInt = [](llvm::APSInt LHS, llvm::APSInt RHS) -> llvm::APSInt {
685
+ if (LHS.isSigned () == RHS.isSigned ())
686
+ return LHS + RHS;
687
+
688
+ unsigned Width = std::max (LHS.getBitWidth (), RHS.getBitWidth ()) + 1 ;
689
+ return llvm::APSInt (LHS.sext (Width) + RHS.sext (Width), /* Signed=*/ true );
690
+ };
691
+
692
+ // If we know all 3 values, we can diagnose that the total value would be out
693
+ // of range.
694
+ if (BaseSize.has_value () && LowerBoundValue.has_value () &&
695
+ LengthValue.has_value () &&
696
+ llvm::APSInt::compareValues (AddAPSInt (*LowerBoundValue, *LengthValue),
697
+ *BaseSize) > 0 ) {
698
+ Diag (Base->getExprLoc (),
699
+ diag::err_acc_subarray_base_plus_length_out_of_range)
700
+ << toString (*LowerBoundValue, /* Radix=*/ 10 )
701
+ << toString (*LengthValue, /* Radix=*/ 10 )
702
+ << toString (*BaseSize, /* Radix=*/ 10 );
703
+
704
+ LowerBoundValue.reset ();
705
+ LowerBound = GetRecovery (LowerBound, LowerBound->getType ());
706
+ LengthValue.reset ();
707
+ Length = GetRecovery (Length, Length->getType ());
708
+ }
709
+
710
+ // If any part of the expression is dependent, return a dependent sub-array.
711
+ QualType ArrayExprTy = Context.ArraySectionTy ;
712
+ if (Base->isTypeDependent () ||
713
+ (LowerBound && LowerBound->isInstantiationDependent ()) ||
714
+ (Length && Length->isInstantiationDependent ()))
715
+ ArrayExprTy = Context.DependentTy ;
716
+
509
717
return new (Context)
510
- ArraySectionExpr (Base, LowerBound, Length, Context. ArraySectionTy ,
511
- VK_LValue, OK_Ordinary, ColonLoc, RBLoc);
718
+ ArraySectionExpr (Base, LowerBound, Length, ArrayExprTy, VK_LValue ,
719
+ OK_Ordinary, ColonLoc, RBLoc);
512
720
}
513
721
514
722
bool SemaOpenACC::ActOnStartStmtDirective (OpenACCDirectiveKind K,
0 commit comments