--- /dev/null
+// 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<TDLC_ClauseA>,
+ VersionedClause<TDLC_ClauseB>
+ ];
+ let allowedOnceClauses = [
+ VersionedClause<TDLC_ClauseA>
+ ];
+ 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
}
}
-// Generate the declaration section for the enumeration in the directive
-// language
-void EmitDirectivesDecl(RecordKeeper &Records, raw_ostream &OS) {
+bool HasDuplicateClauses(const std::vector<Record *> &Clauses,
+ const Directive &Directive,
+ llvm::StringSet<> &CrtClauses) {
+ 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;
+ }
+ }
+ return hasError;
+}
+
+bool HasDuplicateClausesInDirectives(const std::vector<Record *> &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;
+}
+// Check consitency of records. Return true if an error has been detected.
+// Return false if the records are valid.
+bool CheckRecordsValidity(RecordKeeper &Records) {
const auto &DirectiveLanguages =
Records.getAllDerivedDefinitions("DirectiveLanguage");
if (DirectiveLanguages.size() != 1) {
PrintError("A single definition of DirectiveLanguage is needed.");
- return;
+ return true;
}
+ const auto &Directives = Records.getAllDerivedDefinitions("Directive");
+ return HasDuplicateClausesInDirectives(Directives);
+}
+
+// Generate the declaration section for the enumeration in the directive
+// language
+void EmitDirectivesDecl(RecordKeeper &Records, raw_ostream &OS) {
+
+ if (CheckRecordsValidity(Records))
+ return;
+
+ const auto &DirectiveLanguages =
+ Records.getAllDerivedDefinitions("DirectiveLanguage");
+
DirectiveLanguage DirLang{DirectiveLanguages[0]};
+ const auto &Directives = Records.getAllDerivedDefinitions("Directive");
OS << "#ifndef LLVM_" << DirLang.getName() << "_INC\n";
OS << "#define LLVM_" << DirLang.getName() << "_INC\n";
OS << "\nLLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n";
// Emit Directive enumeration
- const auto &Directives = Records.getAllDerivedDefinitions("Directive");
GenerateEnumClass(Directives, OS, "Directive", DirLang.getDirectivePrefix(),
DirLang);
// Generate the implemenation section for the enumeration in the directive
// language.
void EmitDirectivesGen(RecordKeeper &Records, raw_ostream &OS) {
+ if (CheckRecordsValidity(Records))
+ return;
const auto &DirectiveLanguages =
Records.getAllDerivedDefinitions("DirectiveLanguage");
-
- if (DirectiveLanguages.size() != 1) {
- PrintError("A single definition of DirectiveLanguage is needed.");
- return;
- }
-
const auto &Directives = Records.getAllDerivedDefinitions("Directive");
const auto &Clauses = Records.getAllDerivedDefinitions("Clause");
DirectiveLanguage DirectiveLanguage{DirectiveLanguages[0]};
// Generate the implemenation for the enumeration in the directive
// language. This code can be included in library.
void EmitDirectivesImpl(RecordKeeper &Records, raw_ostream &OS) {
+ if (CheckRecordsValidity(Records))
+ return;
const auto &DirectiveLanguages =
Records.getAllDerivedDefinitions("DirectiveLanguage");
-
- if (DirectiveLanguages.size() != 1) {
- PrintError("A single definition of DirectiveLanguage is needed.");
- return;
- }
-
const auto &Directives = Records.getAllDerivedDefinitions("Directive");
-
DirectiveLanguage DirLang = DirectiveLanguage{DirectiveLanguages[0]};
const auto &Clauses = Records.getAllDerivedDefinitions("Clause");