diff --git a/flang/test/Semantics/acc-clause-validity.f90 b/flang/test/Semantics/acc-clause-validity.f90
--- a/flang/test/Semantics/acc-clause-validity.f90
+++ b/flang/test/Semantics/acc-clause-validity.f90
@@ -14,6 +14,7 @@
 !   2.11 Parallel Loop
 !   2.11 Kernels Loop
 !   2.11 Serial Loop
+!   2.14.3 Set
 !   2.16.13 Wait
 
 program openacc_clause_validity
@@ -42,6 +43,32 @@
   !$acc init device_type(2, i, j)
   !$acc init device_num(i) device_type(i, j) if(ifCondition)
 
+  !ERROR: At least one of DEFAULT_ASYNC, DEVICE_NUM, DEVICE_TYPE clause must appear on the SET directive
+  !$acc set
+
+  !ERROR: At least one of DEFAULT_ASYNC, DEVICE_NUM, DEVICE_TYPE clause must appear on the SET directive
+  !$acc set if(.TRUE.)
+
+  !ERROR: At most one DEFAULT_ASYNC clause can appear on the SET directive
+  !$acc set default_async(2) default_async(1)
+
+  !ERROR: At most one DEFAULT_ASYNC clause can appear on the SET directive
+  !$acc set default_async(2) default_async(1)
+
+  !ERROR: At most one DEVICE_NUM clause can appear on the SET directive
+  !$acc set device_num(1) device_num(i)
+
+  !ERROR: At most one DEVICE_TYPE clause can appear on the SET directive
+  !$acc set device_type(i) device_type(2, i, j)
+
+  !$acc set default_async(2)
+  !$acc set default_async(i)
+  !$acc set device_num(1)
+  !$acc set device_num(i)
+  !$acc set device_type(i)
+  !$acc set device_type(2, i, j)
+  !$acc set device_num(1) default_async(2) device_type(2, i, j)
+
   !ERROR: At least one of ATTACH, COPYIN, CREATE clause must appear on the ENTER DATA directive
   !$acc enter data
 
diff --git a/llvm/include/llvm/Frontend/OpenACC/ACC.td b/llvm/include/llvm/Frontend/OpenACC/ACC.td
--- a/llvm/include/llvm/Frontend/OpenACC/ACC.td
+++ b/llvm/include/llvm/Frontend/OpenACC/ACC.td
@@ -415,9 +415,15 @@
 // 2.14.3
 def ACC_Set : Directive<"set"> {
   let allowedOnceClauses = [
+    VersionedClause<ACCC_DefaultAsync>,
+    VersionedClause<ACCC_DeviceNum>,
+    VersionedClause<ACCC_DeviceType>,
     VersionedClause<ACCC_If>
   ];
   let requiredClauses = [
+    // The three following clauses are also in allowedOnceClauses list due to
+    // restriction 2255 - Two instances of the same clause may not appear on the
+    // same directive.
     VersionedClause<ACCC_DefaultAsync>,
     VersionedClause<ACCC_DeviceNum>,
     VersionedClause<ACCC_DeviceType>
diff --git a/llvm/include/llvm/TableGen/DirectiveEmitter.h b/llvm/include/llvm/TableGen/DirectiveEmitter.h
--- a/llvm/include/llvm/TableGen/DirectiveEmitter.h
+++ b/llvm/include/llvm/TableGen/DirectiveEmitter.h
@@ -58,7 +58,7 @@
     return Records.getAllDerivedDefinitions("Clause");
   }
 
-  bool CheckRecordsValidity() const;
+  bool HasValidityErrors() const;
 
 private:
   const llvm::Record *Def;
diff --git a/llvm/utils/TableGen/DirectiveEmitter.cpp b/llvm/utils/TableGen/DirectiveEmitter.cpp
--- a/llvm/utils/TableGen/DirectiveEmitter.cpp
+++ b/llvm/utils/TableGen/DirectiveEmitter.cpp
@@ -114,24 +114,24 @@
 bool HasDuplicateClauses(const std::vector<Record *> &Clauses,
                          const Directive &Directive,
                          llvm::StringSet<> &CrtClauses) {
-  bool hasError = false;
+  bool HasError = false;
   for (const auto &C : Clauses) {
     VersionedClause VerClause{C};
     const auto insRes = CrtClauses.insert(VerClause.getClause().getName());
     if (!insRes.second) {
       PrintError("Clause " + VerClause.getClause().getRecordName() +
                  " already defined on directive " + Directive.getRecordName());
-      hasError = true;
+      HasError = true;
     }
   }
-  return hasError;
+  return HasError;
 }
 
 // Check for duplicate clauses in lists. Clauses cannot appear twice in the
 // three allowed list. Also, since required implies allowed, clauses cannot
 // appear in both the allowedClauses and requiredClauses lists.
 bool HasDuplicateClausesInDirectives(const std::vector<Record *> &Directives) {
-  bool hasDuplicate = false;
+  bool HasDuplicate = false;
   for (const auto &D : Directives) {
     Directive Dir{D};
     llvm::StringSet<> Clauses;
@@ -139,26 +139,26 @@
     if (HasDuplicateClauses(Dir.getAllowedClauses(), Dir, Clauses) ||
         HasDuplicateClauses(Dir.getAllowedOnceClauses(), Dir, Clauses) ||
         HasDuplicateClauses(Dir.getAllowedExclusiveClauses(), Dir, Clauses)) {
-      hasDuplicate = true;
+      HasDuplicate = true;
     }
     // Check for duplicate between allowedClauses and required
     Clauses.clear();
     if (HasDuplicateClauses(Dir.getAllowedClauses(), Dir, Clauses) ||
         HasDuplicateClauses(Dir.getRequiredClauses(), Dir, Clauses)) {
-      hasDuplicate = true;
+      HasDuplicate = true;
     }
-    if (hasDuplicate)
+    if (HasDuplicate)
       PrintFatalError("One or more clauses are defined multiple times on"
                       " directive " +
                       Dir.getRecordName());
   }
 
-  return hasDuplicate;
+  return HasDuplicate;
 }
 
 // Check consitency of records. Return true if an error has been detected.
 // Return false if the records are valid.
-bool DirectiveLanguage::CheckRecordsValidity() const {
+bool DirectiveLanguage::HasValidityErrors() const {
   if (getDirectiveLanguages().size() != 1) {
     PrintFatalError("A single definition of DirectiveLanguage is needed.");
     return true;
@@ -171,7 +171,7 @@
 // language
 void EmitDirectivesDecl(RecordKeeper &Records, raw_ostream &OS) {
   const auto DirLang = DirectiveLanguage{Records};
-  if (DirLang.CheckRecordsValidity())
+  if (DirLang.HasValidityErrors())
     return;
 
   OS << "#ifndef LLVM_" << DirLang.getName() << "_INC\n";
@@ -649,7 +649,7 @@
 // language.
 void EmitDirectivesGen(RecordKeeper &Records, raw_ostream &OS) {
   const auto DirLang = DirectiveLanguage{Records};
-  if (DirLang.CheckRecordsValidity())
+  if (DirLang.HasValidityErrors())
     return;
 
   EmitDirectivesFlangImpl(DirLang, OS);
@@ -659,7 +659,7 @@
 // language. This code can be included in library.
 void EmitDirectivesImpl(RecordKeeper &Records, raw_ostream &OS) {
   const auto DirLang = DirectiveLanguage{Records};
-  if (DirLang.CheckRecordsValidity())
+  if (DirLang.HasValidityErrors())
     return;
 
   if (!DirLang.getIncludeHeader().empty())