diff options
| author | Aaron Ballman <aaron@aaronballman.com> | 2014-11-14 13:44:02 +0000 |
|---|---|---|
| committer | Aaron Ballman <aaron@aaronballman.com> | 2014-11-14 13:44:02 +0000 |
| commit | a0344c5d7b9b748a2244dce393ceb55e83b495d6 (patch) | |
| tree | 41c8abfdc700d4744b5da95832035d84aa13ffa7 /clang/utils/TableGen | |
| parent | c670688addc0a1e8a14b6174ff3626dce82f88ab (diff) | |
| download | bcm5719-llvm-a0344c5d7b9b748a2244dce393ceb55e83b495d6.tar.gz bcm5719-llvm-a0344c5d7b9b748a2244dce393ceb55e83b495d6.zip | |
Complete support for the SD-6 standing document (based off N4200) with support for __has_cpp_attribute.
llvm-svn: 221991
Diffstat (limited to 'clang/utils/TableGen')
| -rw-r--r-- | clang/utils/TableGen/ClangAttrEmitter.cpp | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index a8e1b077d5b..71b5c3650f3 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -1820,6 +1820,27 @@ static void GenerateHasAttrSpellingStringSwitch( const std::vector<Record *> &Attrs, raw_ostream &OS, const std::string &Variety = "", const std::string &Scope = "") { for (const auto *Attr : 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 + // attribute version information should be taken from the SD-6 standing + // document, which can be found at: + // https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations + int Version = 1; + + if (Variety == "CXX11") { + std::vector<Record *> Spellings = Attr->getValueAsListOfDefs("Spellings"); + for (const auto &Spelling : Spellings) { + if (Spelling->getValueAsString("Variety") == "CXX11") { + Version = static_cast<int>(Spelling->getValueAsInt("Version")); + if (Scope.empty() && Version == 1) + PrintError(Spelling->getLoc(), "C++ standard attributes must " + "have valid version information."); + break; + } + } + } + // It is assumed that there will be an llvm::Triple object named T within // scope that can be used to determine whether the attribute exists in // a given target. @@ -1858,16 +1879,16 @@ static void GenerateHasAttrSpellingStringSwitch( // C++11 mode should be checked against LangOpts, which is presumed to be // present in the caller. Test = "LangOpts.CPlusPlus11"; - else - Test = "true"; + std::string TestStr = + !Test.empty() ? Test + " ? " + std::to_string(Version) + " : 0" : "1"; std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr); for (const auto &S : Spellings) if (Variety.empty() || (Variety == S.variety() && (Scope.empty() || Scope == S.nameSpace()))) - OS << " .Case(\"" << S.name() << "\", " << Test << ")\n"; + OS << " .Case(\"" << S.name() << "\", " << TestStr << ")\n"; } - OS << " .Default(false);\n"; + OS << " .Default(0);\n"; } // Emits the list of spellings for attributes. @@ -1899,16 +1920,16 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { OS << "switch (Syntax) {\n"; OS << "case AttrSyntax::Generic:\n"; - OS << " return llvm::StringSwitch<bool>(Name)\n"; + OS << " return llvm::StringSwitch<int>(Name)\n"; GenerateHasAttrSpellingStringSwitch(Attrs, OS); OS << "case AttrSyntax::GNU:\n"; - OS << " return llvm::StringSwitch<bool>(Name)\n"; + OS << " return llvm::StringSwitch<int>(Name)\n"; GenerateHasAttrSpellingStringSwitch(GNU, OS, "GNU"); OS << "case AttrSyntax::Declspec:\n"; - OS << " return llvm::StringSwitch<bool>(Name)\n"; + OS << " return llvm::StringSwitch<int>(Name)\n"; GenerateHasAttrSpellingStringSwitch(Declspec, OS, "Declspec"); OS << "case AttrSyntax::Pragma:\n"; - OS << " return llvm::StringSwitch<bool>(Name)\n"; + OS << " return llvm::StringSwitch<int>(Name)\n"; GenerateHasAttrSpellingStringSwitch(Pragma, OS, "Pragma"); OS << "case AttrSyntax::CXX: {\n"; // C++11-style attributes are further split out based on the Scope. @@ -1921,7 +1942,7 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { OS << "if (!Scope || Scope->getName() == \"\") {\n"; else OS << "if (Scope->getName() == \"" << I->first << "\") {\n"; - OS << " return llvm::StringSwitch<bool>(Name)\n"; + OS << " return llvm::StringSwitch<int>(Name)\n"; GenerateHasAttrSpellingStringSwitch(I->second, OS, "CXX11", I->first); OS << "}"; } |

