diff options
author | Sergei Barannikov <barannikov88@gmail.com> | 2023-09-02 05:22:25 +0300 |
---|---|---|
committer | Sergei Barannikov <barannikov88@gmail.com> | 2023-10-10 09:03:55 +0300 |
commit | 79f87be6888d13a94661be9d8908c83dd2229c9b (patch) | |
tree | c60794cc0bb41e4786c21edc17410cfea819ec8f /clang/utils | |
parent | 792674400f6f04a074a3827349ed0e2ac10067f6 (diff) | |
download | llvm-79f87be6888d13a94661be9d8908c83dd2229c9b.zip llvm-79f87be6888d13a94661be9d8908c83dd2229c9b.tar.gz llvm-79f87be6888d13a94661be9d8908c83dd2229c9b.tar.bz2 |
[clang] Fix several issues in the generated AttrHasAttributeImpl.inc
1. The generated file contained a lot of duplicate switch cases, e.g.:
```
switch (Syntax) {
case AttributeCommonInfo::Syntax::AS_GNU:
return llvm::StringSwitch<int>(Name)
...
.Case("error", 1)
.Case("warning", 1)
.Case("error", 1)
.Case("warning", 1)
```
2. Some attributes were listed in wrong places, e.g.:
```
case AttributeCommonInfo::Syntax::AS_CXX11: {
if (ScopeName == "") {
return llvm::StringSwitch<int>(Name)
...
.Case("warn_unused_result", LangOpts.CPlusPlus11 ? 201907 : 0)
```
`warn_unused_result` is a non-standard attribute and should not be
available as [[warn_unused_result]].
3. Some attributes had the wrong version, e.g.:
```
case AttributeCommonInfo::Syntax::AS_CXX11: {
} else if (ScopeName == "gnu") {
return llvm::StringSwitch<int>(Name)
...
.Case("fallthrough", LangOpts.CPlusPlus11 ? 201603 : 0)
```
[[gnu::fallthrough]] is a non-standard spelling and should not have the
standard version. Instead, __has_cpp_attribute should return 1 for it.
There is another issue with attributes that share spellings, e.g.:
```
.Case("interrupt", true && (T.getArch() == llvm::Triple::arm || ...) ? 1 : 0)
.Case("interrupt", true && (T.getArch() == llvm::Triple::avr) ? 1 : 0)
...
.Case("interrupt", true && (T.getArch() == llvm::Triple::riscv32 || ...) ? 1 : 0)
```
As can be seen, __has_attribute(interrupt) would only return true for
ARM targets. This patch does not address this issue.
Differential Revision: https://reviews.llvm.org/D159393
Diffstat (limited to 'clang/utils')
-rw-r--r-- | clang/utils/TableGen/ClangAttrEmitter.cpp | 73 |
1 files changed, 37 insertions, 36 deletions
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index f2a6c1d..45e2fa7 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -3434,9 +3434,10 @@ static bool GenerateTargetSpecificAttrChecks(const Record *R, } static void GenerateHasAttrSpellingStringSwitch( - const std::vector<Record *> &Attrs, raw_ostream &OS, - const std::string &Variety = "", const std::string &Scope = "") { - for (const auto *Attr : Attrs) { + const std::vector<std::pair<const Record *, FlattenedSpelling>> &Attrs, + raw_ostream &OS, const std::string &Variety, + const std::string &Scope = "") { + for (const auto &[Attr, Spelling] : Attrs) { // C++11-style attributes have specific version information associated with // them. If the attribute has no scope, the version information must not // have the default value (1), as that's incorrect. Instead, the unscoped @@ -3455,26 +3456,22 @@ static void GenerateHasAttrSpellingStringSwitch( // a way that is impactful to the end user. int Version = 1; - std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr); + assert(Spelling.variety() == Variety); std::string Name = ""; - for (const auto &Spelling : Spellings) { - if (Spelling.variety() == Variety && - (Spelling.nameSpace().empty() || Scope == Spelling.nameSpace())) { - Name = Spelling.name(); - Version = static_cast<int>( - Spelling.getSpellingRecord().getValueAsInt("Version")); - // Verify that explicitly specified CXX11 and C23 spellings (i.e. - // not inferred from Clang/GCC spellings) have a version that's - // different than the default (1). - bool RequiresValidVersion = - (Variety == "CXX11" || Variety == "C23") && - Spelling.getSpellingRecord().getValueAsString("Variety") == Variety; - if (RequiresValidVersion && Scope.empty() && Version == 1) - PrintError(Spelling.getSpellingRecord().getLoc(), - "Standard attributes must have " - "valid version information."); - break; - } + if (Spelling.nameSpace().empty() || Scope == Spelling.nameSpace()) { + Name = Spelling.name(); + Version = static_cast<int>( + Spelling.getSpellingRecord().getValueAsInt("Version")); + // Verify that explicitly specified CXX11 and C23 spellings (i.e. + // not inferred from Clang/GCC spellings) have a version that's + // different from the default (1). + bool RequiresValidVersion = + (Variety == "CXX11" || Variety == "C23") && + Spelling.getSpellingRecord().getValueAsString("Variety") == Variety; + if (RequiresValidVersion && Scope.empty() && Version == 1) + PrintError(Spelling.getSpellingRecord().getLoc(), + "Standard attributes must have " + "valid version information."); } std::string Test; @@ -3514,10 +3511,8 @@ static void GenerateHasAttrSpellingStringSwitch( std::string TestStr = !Test.empty() ? Test + " ? " + llvm::itostr(Version) + " : 0" : llvm::itostr(Version); - for (const auto &S : Spellings) - if (Variety.empty() || (Variety == S.variety() && - (Scope.empty() || Scope == S.nameSpace()))) - OS << " .Case(\"" << S.name() << "\", " << TestStr << ")\n"; + if (Scope.empty() || Scope == Spelling.nameSpace()) + OS << " .Case(\"" << Spelling.name() << "\", " << TestStr << ")\n"; } OS << " .Default(0);\n"; } @@ -3550,8 +3545,11 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { // Separate all of the attributes out into four group: generic, C++11, GNU, // and declspecs. Then generate a big switch statement for each of them. std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); - std::vector<Record *> Declspec, Microsoft, GNU, Pragma, HLSLSemantic; - std::map<std::string, std::vector<Record *>> CXX, C23; + std::vector<std::pair<const Record *, FlattenedSpelling>> Declspec, Microsoft, + GNU, Pragma, HLSLSemantic; + std::map<std::string, + std::vector<std::pair<const Record *, FlattenedSpelling>>> + CXX, C23; // Walk over the list of all attributes, and split them out based on the // spelling variety. @@ -3560,19 +3558,19 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { for (const auto &SI : Spellings) { const std::string &Variety = SI.variety(); if (Variety == "GNU") - GNU.push_back(R); + GNU.emplace_back(R, SI); else if (Variety == "Declspec") - Declspec.push_back(R); + Declspec.emplace_back(R, SI); else if (Variety == "Microsoft") - Microsoft.push_back(R); + Microsoft.emplace_back(R, SI); else if (Variety == "CXX11") - CXX[SI.nameSpace()].push_back(R); + CXX[SI.nameSpace()].emplace_back(R, SI); else if (Variety == "C23") - C23[SI.nameSpace()].push_back(R); + C23[SI.nameSpace()].emplace_back(R, SI); else if (Variety == "Pragma") - Pragma.push_back(R); + Pragma.emplace_back(R, SI); else if (Variety == "HLSLSemantic") - HLSLSemantic.push_back(R); + HLSLSemantic.emplace_back(R, SI); } } @@ -3594,7 +3592,10 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { OS << " return llvm::StringSwitch<int>(Name)\n"; GenerateHasAttrSpellingStringSwitch(HLSLSemantic, OS, "HLSLSemantic"); auto fn = [&OS](const char *Spelling, - const std::map<std::string, std::vector<Record *>> &List) { + const std::map< + std::string, + std::vector<std::pair<const Record *, FlattenedSpelling>>> + &List) { OS << "case AttributeCommonInfo::Syntax::AS_" << Spelling << ": {\n"; // C++11-style attributes are further split out based on the Scope. for (auto I = List.cbegin(), E = List.cend(); I != E; ++I) { |