Skip to content

Commit 393ccc1

Browse files
committed
[clang][TableGen] Fix Duplicate Entries in TableGen
Fixed TableGen duplicate issues that causes the wrong interrupt attribute from being selected. resolves llvm#140701
1 parent 3f196e0 commit 393ccc1

File tree

2 files changed

+38
-5
lines changed

2 files changed

+38
-5
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %clang_cc1 -triple riscv64 -ast-dump -ast-dump-filter c23 -std=c23 -x c %s | FileCheck --strict-whitespace %s
2+
3+
// CHECK: FunctionDecl{{.*}}pre_c23
4+
// CHECK-NEXT: |-CompoundStmt
5+
// CHECK-NEXT: `-RISCVInterruptAttr{{.*}}supervisor
6+
__attribute__((interrupt("supervisor"))) void pre_c23(){}
7+
8+
// CHECK: FunctionDecl{{.*}}in_c23
9+
// CHECK-NEXT: |-CompoundStmt
10+
// CHECK-NEXT: `-RISCVInterruptAttr{{.*}}supervisor
11+
// CHECK-NOT: `-RISCVInterruptAttr{{.*}}machine
12+
[[gnu::interrupt("supervisor")]] void in_c23(){}

clang/utils/TableGen/ClangAttrEmitter.cpp

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "llvm/ADT/STLExtras.h"
2121
#include "llvm/ADT/SmallString.h"
2222
#include "llvm/ADT/StringExtras.h"
23+
#include "llvm/ADT/StringMap.h"
2324
#include "llvm/ADT/StringRef.h"
2425
#include "llvm/ADT/StringSwitch.h"
2526
#include "llvm/Support/ErrorHandling.h"
@@ -3667,6 +3668,12 @@ static bool GenerateTargetSpecificAttrChecks(const Record *R,
36673668
static void GenerateHasAttrSpellingStringSwitch(
36683669
ArrayRef<std::pair<const Record *, FlattenedSpelling>> Attrs,
36693670
raw_ostream &OS, StringRef Variety, StringRef Scope = "") {
3671+
3672+
// It turns out that duplicate records for a given spelling. This map combines
3673+
// matching test strings using '||'. For example, if there are three
3674+
// conditions A, B, and C, the final result will be: A || B || C.
3675+
llvm::StringMap<std::string> TestStringMap;
3676+
36703677
for (const auto &[Attr, Spelling] : Attrs) {
36713678
// C++11-style attributes have specific version information associated with
36723679
// them. If the attribute has no scope, the version information must not
@@ -3727,12 +3734,26 @@ static void GenerateHasAttrSpellingStringSwitch(
37273734
}
37283735
}
37293736

3730-
std::string TestStr = !Test.empty()
3731-
? Test + " ? " + itostr(Version) + " : 0"
3732-
: itostr(Version);
3733-
if (Scope.empty() || Scope == Spelling.nameSpace())
3734-
OS << " .Case(\"" << Spelling.name() << "\", " << TestStr << ")\n";
3737+
std::string TestStr =
3738+
!Test.empty() ? '(' + Test + " ? " + itostr(Version) + " : 0" + ')'
3739+
: '(' + itostr(Version) + ')';
3740+
3741+
if (Scope.empty() || Scope == Spelling.nameSpace()) {
3742+
if (TestStringMap.contains(Spelling.name())) {
3743+
TestStringMap[Spelling.name()] += " || " + TestStr;
3744+
} else {
3745+
TestStringMap[Spelling.name()] = TestStr;
3746+
}
3747+
}
3748+
}
3749+
3750+
// Create the actual string switch statement after all the attributes have
3751+
// been parsed
3752+
for (auto &entry : TestStringMap) {
3753+
OS << " .Case(\"" << entry.getKey() << "\", " << entry.getValue()
3754+
<< ")\n";
37353755
}
3756+
37363757
OS << " .Default(0);\n";
37373758
}
37383759

0 commit comments

Comments
 (0)