From 9feedb862e46f46d302f250ade1cac7108ba880b Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Mon, 4 Nov 2013 12:55:56 +0000 Subject: [PATCH] Attributes which accept a type as their sole argument are no longer hard coded into the parser. Instead, they are automatically listed through tablegen. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@193989 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Parse/CMakeLists.txt | 5 +++++ lib/Parse/ParseDecl.cpp | 24 +++++++++++++++------- utils/TableGen/ClangAttrEmitter.cpp | 31 +++++++++++++++++++++++++++++ utils/TableGen/TableGen.cpp | 8 ++++++++ utils/TableGen/TableGenBackends.h | 1 + 5 files changed, 62 insertions(+), 7 deletions(-) diff --git a/include/clang/Parse/CMakeLists.txt b/include/clang/Parse/CMakeLists.txt index 8a26128150..ed80c1889c 100644 --- a/include/clang/Parse/CMakeLists.txt +++ b/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/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 27b4919b34..c590493313 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/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(Name) + return Name; +} + +/// \brief Determine whether the given attribute has an identifier argument. +static bool attributeHasIdentifierArg(const IdentifierInfo &II) { + return llvm::StringSwitch(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(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/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index 2f758f2a0c..653d7b79e2 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/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 Attrs = Records.getAllDerivedDefinitions("Attr"); + + for (std::vector::iterator I = Attrs.begin(), E = Attrs.end(); + I != E; ++I) { + Record &Attr = **I; + + // Determine whether the first argument is a type. + std::vector 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 Spellings = Attr.getValueAsListOfDefs("Spellings"); + std::set Emitted; + for (std::vector::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/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index d573ecc09a..0e45d81d1a 100644 --- a/utils/TableGen/TableGen.cpp +++ b/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 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/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h index 426b0155a7..8904287060 100644 --- a/utils/TableGen/TableGenBackends.h +++ b/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); -- 2.40.0