@@ -335,29 +335,106 @@ class SemaOpenACCClauseVisitor {
335335
336336 // For 'tile' and 'collapse', only allow 1 per 'device_type'.
337337 // Also applies to num_worker, num_gangs, vector_length, and async.
338+ // This does introspection into the actual device-types to prevent duplicates
339+ // across device types as well.
338340 template <typename TheClauseTy>
339341 bool DisallowSinceLastDeviceType (SemaOpenACC::OpenACCParsedClause &Clause) {
340342 auto LastDeviceTypeItr =
341343 std::find_if (ExistingClauses.rbegin (), ExistingClauses.rend (),
342344 llvm::IsaPred<OpenACCDeviceTypeClause>);
343345
344- auto Last = std::find_if (ExistingClauses.rbegin (), LastDeviceTypeItr,
345- llvm::IsaPred<TheClauseTy>);
346+ auto LastSinceDevTy =
347+ std::find_if (ExistingClauses.rbegin (), LastDeviceTypeItr,
348+ llvm::IsaPred<TheClauseTy>);
346349
347- if (Last == LastDeviceTypeItr)
350+ // In this case there is a duplicate since the last device_type/lack of a
351+ // device_type. Diagnose these as duplicates.
352+ if (LastSinceDevTy != LastDeviceTypeItr) {
353+ SemaRef.Diag (Clause.getBeginLoc (),
354+ diag::err_acc_clause_since_last_device_type)
355+ << Clause.getClauseKind () << Clause.getDirectiveKind ()
356+ << (LastDeviceTypeItr != ExistingClauses.rend ());
357+ SemaRef.Diag ((*LastSinceDevTy)->getBeginLoc (),
358+ diag::note_acc_previous_clause_here);
359+
360+ // Mention the last device_type as well.
361+ if (LastDeviceTypeItr != ExistingClauses.rend ())
362+ SemaRef.Diag ((*LastDeviceTypeItr)->getBeginLoc (),
363+ diag::note_acc_previous_clause_here);
364+ return true ;
365+ }
366+
367+ // If this isn't in a device_type, and we didn't diagnose that there are
368+ // dupes above, just give up, no sense in searching for previous device_type
369+ // regions as they don't exist.
370+ if (LastDeviceTypeItr == ExistingClauses.rend ())
348371 return false ;
349372
350- SemaRef.Diag (Clause.getBeginLoc (),
351- diag::err_acc_clause_since_last_device_type)
352- << Clause.getClauseKind () << Clause.getDirectiveKind ()
353- << (LastDeviceTypeItr != ExistingClauses.rend ());
354- SemaRef.Diag ((*Last)->getBeginLoc (), diag::note_acc_previous_clause_here);
373+ // The device-type that is active for us, so we can compare to the previous
374+ // ones.
375+ const auto &ActiveDeviceTypeClause =
376+ cast<OpenACCDeviceTypeClause>(**LastDeviceTypeItr);
355377
356- if (LastDeviceTypeItr != ExistingClauses.rend ())
357- SemaRef.Diag ((*LastDeviceTypeItr)->getBeginLoc (),
358- diag::note_acc_previous_clause_here);
378+ auto PrevDeviceTypeItr = LastDeviceTypeItr;
379+ auto CurDevTypeItr = LastDeviceTypeItr;
359380
360- return true ;
381+ while ((CurDevTypeItr = std::find_if (
382+ std::next (PrevDeviceTypeItr), ExistingClauses.rend (),
383+ llvm::IsaPred<OpenACCDeviceTypeClause>)) !=
384+ ExistingClauses.rend ()) {
385+ // At this point, we know that we have a region between two device_types,
386+ // as specified by CurDevTypeItr and PrevDeviceTypeItr.
387+
388+ auto CurClauseKindItr = std::find_if (PrevDeviceTypeItr, CurDevTypeItr,
389+ llvm::IsaPred<TheClauseTy>);
390+
391+ // There are no clauses of the current kind between these device_types, so
392+ // continue.
393+ if (CurClauseKindItr == CurDevTypeItr)
394+ continue ;
395+
396+ // At this point, we know that this device_type region has a collapse. So
397+ // diagnose if the two device_types have any overlap in their
398+ // architectures.
399+ const auto &CurDeviceTypeClause =
400+ cast<OpenACCDeviceTypeClause>(**CurDevTypeItr);
401+
402+ for (const DeviceTypeArgument &arg :
403+ ActiveDeviceTypeClause.getArchitectures ()) {
404+ for (const DeviceTypeArgument &prevArg :
405+ CurDeviceTypeClause.getArchitectures ()) {
406+
407+ // This should catch duplicates * regions, duplicate same-text (thanks
408+ // to identifier equiv.) and case insensitive dupes.
409+ if (arg.getIdentifierInfo () == prevArg.getIdentifierInfo () ||
410+ (arg.getIdentifierInfo () && prevArg.getIdentifierInfo () &&
411+ StringRef{arg.getIdentifierInfo ()->getName ()}.equals_insensitive (
412+ prevArg.getIdentifierInfo ()->getName ()))) {
413+ SemaRef.Diag (Clause.getBeginLoc (),
414+ diag::err_acc_clause_conflicts_prev_dev_type)
415+ << Clause.getClauseKind ()
416+ << (arg.getIdentifierInfo () ? arg.getIdentifierInfo ()->getName ()
417+ : " *" );
418+ // mention the active device type.
419+ SemaRef.Diag (ActiveDeviceTypeClause.getBeginLoc (),
420+ diag::note_acc_device_type_here)
421+ << diag::ACCDeviceTypeApp::Active;
422+ // mention the previous clause.
423+ SemaRef.Diag ((*CurClauseKindItr)->getBeginLoc (),
424+ diag::note_acc_previous_named_clause_here)
425+ << (*CurClauseKindItr)->getClauseKind ();
426+ // mention the previous device type.
427+ SemaRef.Diag (CurDeviceTypeClause.getBeginLoc (),
428+ diag::note_acc_device_type_here)
429+ << diag::ACCDeviceTypeApp::Applies;
430+ return true ;
431+ }
432+ }
433+ }
434+
435+ PrevDeviceTypeItr = CurDevTypeItr;
436+ }
437+ return false ;
361438 }
362439
363440public:
0 commit comments