@@ -1338,13 +1338,50 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceTypeClause(
13381338 checkAlreadyHasClauseOfKind (SemaRef, ExistingClauses, Clause))
13391339 return nullptr ;
13401340
1341- // TODO OpenACC: Once we get enough of the CodeGen implemented that we have
1342- // a source for the list of valid architectures, we need to warn on unknown
1343- // identifiers here.
1341+ // The list of valid device_type values. Flang also has these hardcoded in
1342+ // openacc_parsers.cpp, as there does not seem to be a reliable backend
1343+ // source. The list below is sourced from Flang, though NVC++ supports only
1344+ // 'nvidia', 'host', 'multicore', and 'default'.
1345+ const std::array<llvm::StringLiteral, 6 > ValidValues{
1346+ " default" , " nvidia" , " acc_device_nvidia" , " radeon" , " host" , " multicore" };
1347+ // As an optimization, we have a manually maintained list of valid values
1348+ // below, rather than trying to calculate from above. These should be kept in
1349+ // sync if/when the above list ever changes.
1350+ std::string ValidValuesString =
1351+ " 'default', 'nvidia', 'acc_device_nvidia', 'radeon', 'host', 'multicore'" ;
1352+
1353+ llvm::SmallVector<DeviceTypeArgument> Architectures{
1354+ Clause.getDeviceTypeArchitectures ()};
1355+
1356+ // The parser has ensured that we either have a single entry of just '*'
1357+ // (represented by a nullptr IdentifierInfo), or a list.
1358+
1359+ bool Diagnosed = false ;
1360+ auto FilterPred = [&](const DeviceTypeArgument &Arch) {
1361+ // The '*' case.
1362+ if (!Arch.first )
1363+ return false ;
1364+ return llvm::find_if (ValidValues, [&](StringRef RHS) {
1365+ return Arch.first ->getName ().equals_insensitive (RHS);
1366+ }) == ValidValues.end ();
1367+ };
1368+
1369+ auto Diagnose = [&](const DeviceTypeArgument &Arch) {
1370+ Diagnosed = SemaRef.Diag (Arch.second , diag::err_acc_invalid_default_type)
1371+ << Arch.first << Clause.getClauseKind () << ValidValuesString;
1372+ };
1373+
1374+ // There aren't stable enumertor versions of 'for-each-then-erase', so do it
1375+ // here. We DO keep track of whether we diagnosed something to make sure we
1376+ // don't do the 'erase_if' in the event that the first list didn't find
1377+ // anything.
1378+ llvm::for_each (llvm::make_filter_range (Architectures, FilterPred), Diagnose);
1379+ if (Diagnosed)
1380+ llvm::erase_if (Architectures, FilterPred);
13441381
13451382 return OpenACCDeviceTypeClause::Create (
13461383 Ctx, Clause.getClauseKind (), Clause.getBeginLoc (), Clause.getLParenLoc (),
1347- Clause. getDeviceTypeArchitectures () , Clause.getEndLoc ());
1384+ Architectures , Clause.getEndLoc ());
13481385}
13491386
13501387OpenACCClause *SemaOpenACCClauseVisitor::VisitAutoClause (
0 commit comments