diff options
author | Aaron Ballman <aaron@aaronballman.com> | 2013-11-04 12:55:56 +0000 |
---|---|---|
committer | Aaron Ballman <aaron@aaronballman.com> | 2013-11-04 12:55:56 +0000 |
commit | 4768b3179738c723bbab66b100a26f05457f9a87 (patch) | |
tree | b3abedb65bde3431f769afb870625a6fe31ae9bd /clang | |
parent | 46eeaba93bf84e19b8e6c7d0a251dd1c2bc4789d (diff) | |
download | bcm5719-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.txt | 5 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 24 | ||||
-rw-r--r-- | clang/utils/TableGen/ClangAttrEmitter.cpp | 31 | ||||
-rw-r--r-- | clang/utils/TableGen/TableGen.cpp | 8 | ||||
-rw-r--r-- | clang/utils/TableGen/TableGenBackends.h | 1 |
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); |