summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorAaron Ballman <aaron@aaronballman.com>2013-11-04 12:55:56 +0000
committerAaron Ballman <aaron@aaronballman.com>2013-11-04 12:55:56 +0000
commit4768b3179738c723bbab66b100a26f05457f9a87 (patch)
treeb3abedb65bde3431f769afb870625a6fe31ae9bd /clang
parent46eeaba93bf84e19b8e6c7d0a251dd1c2bc4789d (diff)
downloadbcm5719-llvm-4768b3179738c723bbab66b100a26f05457f9a87.tar.gz
bcm5719-llvm-4768b3179738c723bbab66b100a26f05457f9a87.zip
Attributes which accept a type as their sole argument are no longer hard coded into the parser. Instead, they are automatically listed through tablegen.
llvm-svn: 193989
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Parse/CMakeLists.txt5
-rw-r--r--clang/lib/Parse/ParseDecl.cpp24
-rw-r--r--clang/utils/TableGen/ClangAttrEmitter.cpp31
-rw-r--r--clang/utils/TableGen/TableGen.cpp8
-rw-r--r--clang/utils/TableGen/TableGenBackends.h1
5 files changed, 62 insertions, 7 deletions
diff --git a/clang/include/clang/Parse/CMakeLists.txt b/clang/include/clang/Parse/CMakeLists.txt
index 8a261281501..ed80c1889c7 100644
--- a/clang/include/clang/Parse/CMakeLists.txt
+++ b/clang/include/clang/Parse/CMakeLists.txt
@@ -3,6 +3,11 @@ clang_tablegen(AttrIdentifierArg.inc -gen-clang-attr-identifier-arg-list
SOURCE ../Basic/Attr.td
TARGET ClangAttrIdentifierArg)
+clang_tablegen(AttrTypeArg.inc -gen-clang-attr-type-arg-list
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
+ SOURCE ../Basic/Attr.td
+ TARGET ClangAttrTypeArg)
+
clang_tablegen(AttrLateParsed.inc -gen-clang-attr-late-parsed-list
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
SOURCE ../Basic/Attr.td
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 27b4919b342..c5904933133 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -181,16 +181,27 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
}
}
-/// \brief Determine whether the given attribute has an identifier argument.
-static bool attributeHasIdentifierArg(const IdentifierInfo &II) {
- StringRef Name = II.getName();
+/// \brief Normalizes an attribute name by dropping prefixed and suffixed __.
+static StringRef normalizeAttrName(StringRef Name) {
if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
Name = Name.drop_front(2).drop_back(2);
- return llvm::StringSwitch<bool>(Name)
+ return Name;
+}
+
+/// \brief Determine whether the given attribute has an identifier argument.
+static bool attributeHasIdentifierArg(const IdentifierInfo &II) {
+ return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
#include "clang/Parse/AttrIdentifierArg.inc"
.Default(false);
}
+/// \brief Determine whether the given attribute parses a type argument.
+static bool attributeIsTypeArgAttr(const IdentifierInfo &II) {
+ return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
+#include "clang/Parse/AttrTypeArg.inc"
+ .Default(false);
+}
+
IdentifierLoc *Parser::ParseIdentifierLoc() {
assert(Tok.is(tok::identifier) && "expected an identifier");
IdentifierLoc *IL = IdentifierLoc::create(Actions.Context,
@@ -260,9 +271,8 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc);
return;
}
- // __attribute__((vec_type_hint)) and iboutletcollection expect a type arg.
- if (AttrKind == AttributeList::AT_VecTypeHint ||
- AttrKind == AttributeList::AT_IBOutletCollection) {
+ // Some attributes expect solely a type parameter.
+ if (attributeIsTypeArgAttr(*AttrName)) {
ParseAttributeWithTypeArg(*AttrName, AttrNameLoc, Attrs, EndLoc);
return;
}
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index 2f758f2a0cb..653d7b79e28 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -1195,6 +1195,37 @@ static bool isIdentifierArgument(Record *Arg) {
.Default(false);
}
+/// \brief Emits the first-argument-is-type property for attributes.
+void EmitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) {
+ emitSourceFileHeader("llvm::StringSwitch code to match attributes with a "
+ "type argument", OS);
+
+ std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
+
+ for (std::vector<Record *>::iterator I = Attrs.begin(), E = Attrs.end();
+ I != E; ++I) {
+ Record &Attr = **I;
+
+ // Determine whether the first argument is a type.
+ std::vector<Record *> Args = Attr.getValueAsListOfDefs("Args");
+ if (Args.empty())
+ continue;
+
+ if (Args[0]->getSuperClasses().back()->getName() != "TypeArgument")
+ continue;
+
+ // All these spellings take a single type argument.
+ std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
+ std::set<std::string> Emitted;
+ for (std::vector<Record*>::const_iterator I = Spellings.begin(),
+ E = Spellings.end(); I != E; ++I) {
+ if (Emitted.insert((*I)->getValueAsString("Name")).second)
+ OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", "
+ << "true" << ")\n";
+ }
+ }
+}
+
// Emits the first-argument-is-identifier property for attributes.
void EmitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader("llvm::StringSwitch code to match attributes with "
diff --git a/clang/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp
index d573ecc09ab..0e45d81d1af 100644
--- a/clang/utils/TableGen/TableGen.cpp
+++ b/clang/utils/TableGen/TableGen.cpp
@@ -25,6 +25,7 @@ using namespace clang;
enum ActionType {
GenClangAttrClasses,
GenClangAttrIdentifierArgList,
+ GenClangAttrTypeArgList,
GenClangAttrImpl,
GenClangAttrList,
GenClangAttrPCHRead,
@@ -64,6 +65,10 @@ cl::opt<ActionType> Action(
"gen-clang-attr-identifier-arg-list",
"Generate a list of attributes that take an "
"identifier as their first argument"),
+ clEnumValN(GenClangAttrTypeArgList,
+ "gen-clang-attr-type-arg-list",
+ "Generate a list of attributes that take a type as their "
+ "first argument"),
clEnumValN(GenClangAttrImpl, "gen-clang-attr-impl",
"Generate clang attribute implementations"),
clEnumValN(GenClangAttrList, "gen-clang-attr-list",
@@ -145,6 +150,9 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenClangAttrIdentifierArgList:
EmitClangAttrIdentifierArgList(Records, OS);
break;
+ case GenClangAttrTypeArgList:
+ EmitClangAttrTypeArgList(Records, OS);
+ break;
case GenClangAttrImpl:
EmitClangAttrImpl(Records, OS);
break;
diff --git a/clang/utils/TableGen/TableGenBackends.h b/clang/utils/TableGen/TableGenBackends.h
index 426b0155a78..89042870606 100644
--- a/clang/utils/TableGen/TableGenBackends.h
+++ b/clang/utils/TableGen/TableGenBackends.h
@@ -31,6 +31,7 @@ void EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS,
void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS);
+void EmitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS);
OpenPOWER on IntegriCloud