@@ -519,8 +519,31 @@ bool SemaOpenACC::CheckVarIsPointerType(OpenACCClauseKind ClauseKind,
519519 return false ;
520520}
521521
522+ void SemaOpenACC::ActOnStartParseVar (OpenACCDirectiveKind DK,
523+ OpenACCClauseKind CK) {
524+ if (DK == OpenACCDirectiveKind::Cache) {
525+ CacheInfo.ParsingCacheVarList = true ;
526+ CacheInfo.IsInvalidCacheRef = false ;
527+ }
528+ }
529+
530+ void SemaOpenACC::ActOnInvalidParseVar () {
531+ CacheInfo.ParsingCacheVarList = false ;
532+ CacheInfo.IsInvalidCacheRef = false ;
533+ }
534+
522535ExprResult SemaOpenACC::ActOnCacheVar (Expr *VarExpr) {
523536 Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts ();
537+ // Clear this here, so we can do the returns based on the invalid cache ref
538+ // here. Note all return statements in this function must return ExprError if
539+ // IsInvalidCacheRef. However, instead of doing an 'early return' in that
540+ // case, we can let the rest of the diagnostics happen, as the invalid decl
541+ // ref is a warning.
542+ bool WasParsingInvalidCacheRef =
543+ CacheInfo.ParsingCacheVarList && CacheInfo.IsInvalidCacheRef ;
544+ CacheInfo.ParsingCacheVarList = false ;
545+ CacheInfo.IsInvalidCacheRef = false ;
546+
524547 if (!isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) {
525548 Diag (VarExpr->getExprLoc (), diag::err_acc_not_a_var_ref_cache);
526549 return ExprError ();
@@ -540,19 +563,19 @@ ExprResult SemaOpenACC::ActOnCacheVar(Expr *VarExpr) {
540563 if (const auto *DRE = dyn_cast<DeclRefExpr>(CurVarExpr)) {
541564 if (isa<VarDecl, NonTypeTemplateParmDecl>(
542565 DRE->getFoundDecl ()->getCanonicalDecl ()))
543- return VarExpr;
566+ return WasParsingInvalidCacheRef ? ExprEmpty () : VarExpr;
544567 }
545568
546569 if (const auto *ME = dyn_cast<MemberExpr>(CurVarExpr)) {
547570 if (isa<FieldDecl>(ME->getMemberDecl ()->getCanonicalDecl ())) {
548- return VarExpr;
571+ return WasParsingInvalidCacheRef ? ExprEmpty () : VarExpr;
549572 }
550573 }
551574
552575 // Nothing really we can do here, as these are dependent. So just return they
553576 // are valid.
554577 if (isa<DependentScopeDeclRefExpr, CXXDependentScopeMemberExpr>(CurVarExpr))
555- return VarExpr;
578+ return WasParsingInvalidCacheRef ? ExprEmpty () : VarExpr;
556579
557580 // There isn't really anything we can do in the case of a recovery expr, so
558581 // skip the diagnostic rather than produce a confusing diagnostic.
@@ -562,6 +585,45 @@ ExprResult SemaOpenACC::ActOnCacheVar(Expr *VarExpr) {
562585 Diag (VarExpr->getExprLoc (), diag::err_acc_not_a_var_ref_cache);
563586 return ExprError ();
564587}
588+
589+ void SemaOpenACC::CheckDeclReference (SourceLocation Loc, Expr *E, Decl *D) {
590+ if (!getLangOpts ().OpenACC || !CacheInfo.ParsingCacheVarList || !D ||
591+ D->isInvalidDecl ())
592+ return ;
593+ // A 'cache' variable reference MUST be declared before the 'acc.loop' we
594+ // generate in codegen, so we have to mark it invalid here in some way. We do
595+ // so in a bit of a convoluted way as there is no good way to put this into
596+ // the AST, so we store it in SemaOpenACC State. We can check the Scope
597+ // during parsing to make sure there is a 'loop' before the decl is
598+ // declared(and skip during instantiation).
599+ // We only diagnose this as a warning, as this isn't required by the standard
600+ // (unless you take a VERY awkward reading of some awkward prose).
601+
602+ Scope *CurScope = SemaRef.getCurScope ();
603+
604+ // if we are at TU level, we are either doing some EXTRA wacky, or are in a
605+ // template instantiation, so just give up.
606+ if (CurScope->getDepth () == 0 )
607+ return ;
608+
609+ while (CurScope) {
610+ // If we run into a loop construct scope, than this is 'correct' in that the
611+ // declaration is outside of the loop.
612+ if (CurScope->isOpenACCLoopConstructScope ())
613+ return ;
614+
615+ if (CurScope->isDeclScope (D)) {
616+ Diag (Loc, diag::warn_acc_cache_var_not_outside_loop);
617+
618+ CacheInfo.IsInvalidCacheRef = true ;
619+ }
620+
621+ CurScope = CurScope->getParent ();
622+ }
623+ // If we don't find the decl at all, we assume that it must be outside of the
624+ // loop (or we aren't in a loop!) so skip the diagnostic.
625+ }
626+
565627ExprResult SemaOpenACC::ActOnVar (OpenACCDirectiveKind DK, OpenACCClauseKind CK,
566628 Expr *VarExpr) {
567629 // This has unique enough restrictions that we should split it to a separate
0 commit comments