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 @@ -517,7 +517,6 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, 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 @@ -73,6 +73,9 @@ bool isDefault() const { return Def->getValueAsBit("isDefault"); } + // Returns the record name. + const StringRef getRecordName() const { return Def->getName(); } + protected: const llvm::Record *Def; }; diff --git a/llvm/test/TableGen/directive3.td b/llvm/test/TableGen/directive3.td new file mode 100644 --- /dev/null +++ b/llvm/test/TableGen/directive3.td @@ -0,0 +1,30 @@ +// RUN: not llvm-tblgen -gen-directive-decl -I %p/../../include %s 2>&1 | FileCheck -match-full-lines %s +// RUN: not llvm-tblgen -gen-directive-impl -I %p/../../include %s 2>&1 | FileCheck -match-full-lines %s +// RUN: not llvm-tblgen -gen-directive-gen -I %p/../../include %s 2>&1 | FileCheck -match-full-lines %s + +include "llvm/Frontend/Directive/DirectiveBase.td" + +def TestDirectiveLanguage : DirectiveLanguage { + let name = "TdlError"; +} + +def TDLC_ClauseA : Clause<"clausea"> { + let isDefault = 1; +} + +def TDLC_ClauseB : Clause<"clauseb"> { +} + +def TDL_DirA : Directive<"dira"> { + let allowedClauses = [ + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ + VersionedClause + ]; + let isDefault = 1; +} + +// CHECK: error: Clause TDLC_ClauseA already defined on directive TDL_DirA +// CHECK: error: One or more clauses are defined multiple times on directive TDL_DirA 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 @@ -111,6 +111,39 @@ } } +bool HasDuplicateClauses(const std::vector &Clauses, + const Directive &Directive, + llvm::StringSet<> &CrtClauses) { + for (const auto &C : Clauses) { + VersionedClause VerClause{C}; + if (CrtClauses.find(VerClause.getClause().getName()) == CrtClauses.end()) { + CrtClauses.insert(VerClause.getClause().getName()); + } else { + PrintError("Clause " + VerClause.getClause().getRecordName() + + " already defined on directive " + Directive.getRecordName()); + return true; + } + } + return false; +} + +bool HasDuplicateClausesInDirectives(const std::vector &Directives) { + for (const auto &D : Directives) { + Directive Dir{D}; + llvm::StringSet<> Clauses; + if (HasDuplicateClauses(Dir.getAllowedClauses(), Dir, Clauses) || + HasDuplicateClauses(Dir.getAllowedOnceClauses(), Dir, Clauses) || + HasDuplicateClauses(Dir.getAllowedExclusiveClauses(), Dir, Clauses) || + HasDuplicateClauses(Dir.getRequiredClauses(), Dir, Clauses)) { + PrintFatalError( + "One or more clauses are defined multiple times on directive " + + Dir.getRecordName()); + return true; + } + } + return false; +} + // Generate the declaration section for the enumeration in the directive // language void EmitDirectivesDecl(RecordKeeper &Records, raw_ostream &OS) { @@ -124,6 +157,9 @@ } DirectiveLanguage DirLang{DirectiveLanguages[0]}; + const auto &Directives = Records.getAllDerivedDefinitions("Directive"); + if (HasDuplicateClausesInDirectives(Directives)) + return; OS << "#ifndef LLVM_" << DirLang.getName() << "_INC\n"; OS << "#define LLVM_" << DirLang.getName() << "_INC\n"; @@ -145,7 +181,6 @@ OS << "\nLLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n"; // Emit Directive enumeration - const auto &Directives = Records.getAllDerivedDefinitions("Directive"); GenerateEnumClass(Directives, OS, "Directive", DirLang.getDirectivePrefix(), DirLang); @@ -615,6 +650,9 @@ } const auto &Directives = Records.getAllDerivedDefinitions("Directive"); + if (HasDuplicateClausesInDirectives(Directives)) + return; + const auto &Clauses = Records.getAllDerivedDefinitions("Clause"); DirectiveLanguage DirectiveLanguage{DirectiveLanguages[0]}; EmitDirectivesFlangImpl(Directives, Clauses, OS, DirectiveLanguage); @@ -633,6 +671,8 @@ } const auto &Directives = Records.getAllDerivedDefinitions("Directive"); + if (HasDuplicateClausesInDirectives(Directives)) + return; DirectiveLanguage DirLang = DirectiveLanguage{DirectiveLanguages[0]};