//===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// These tablegen backends emit Clang attribute processing code
//
//===----------------------------------------------------------------------===//
#include "ClangAttrEmitter.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/StringMatcher.h"
#include <algorithm>
#include <cctype>
#include <set>
using namespace llvm;
static const std::vector<StringRef>
getValueAsListOfStrings(Record &R, StringRef FieldName) {
ListInit *List = R.getValueAsListInit(FieldName);
assert (List && "Got a null ListInit");
std::vector<StringRef> Strings;
Strings.reserve(List->getSize());
for (ListInit::const_iterator i = List->begin(), e = List->end();
i != e;
++i) {
assert(*i && "Got a null element in a ListInit");
if (StringInit *S = dynamic_cast<StringInit *>(*i))
Strings.push_back(S->getValue());
else
assert(false && "Got a non-string, non-code element in a ListInit");
}
return Strings;
}
static std::string ReadPCHRecord(StringRef type) {
return StringSwitch<std::string>(type)
.EndsWith("Decl *", "GetLocalDeclAs<"
+ std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])")
.Case("QualType", "getLocalType(F, Record[Idx++])")
.Case("Expr *", "ReadSubExpr()")
.Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)")
.Case("SourceLocation", "ReadSourceLocation(F, Record, Idx)")
.Default("Record[Idx++]");
}
// Assumes that the way to get the value is SA->getname()
static std::string WritePCHRecord(StringRef type, StringRef name) {
return StringSwitch<std::string>(type)
.EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
", Record);\n")
.Case("QualType", "AddTypeRef(" + std::string(name) + ", Record);\n")
.Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
.Case("IdentifierInfo *",
"AddIdentifierRef(" + std::string(name) + ", Record);\n")
.Case("SourceLocation",
"AddSourceLocation(" + std::string(name) + ", Record);\n")
.Default("Record.push_back(" + std::string(name) + ");\n");
}
// Normalize attribute name by removing leading and trailing
// underscores. For example, __foo, foo__, __foo__ would
// become foo.
static StringRef NormalizeAttrName(StringRef AttrName) {
if (AttrName.startswith("__"))
AttrName = AttrName.substr(2, AttrName.size());
if (AttrName.endswith("__"))
AttrName = AttrName.substr(0, AttrName.size() - 2);
return AttrName;
}
// Normalize attribute spelling only if the spelling has both leading
// and trailing underscores. For example, __ms_struct__ will be
// normalized to "ms_struct"; __cdecl will remain intact.
static StringRef NormalizeAttrSpelling(StringRef AttrSpelling) {
if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) {
AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4);
}