-clang_tablegen(AttrExprArgs.inc -gen-clang-attr-expr-args-list
+clang_tablegen(AttrIdentifierArg.inc -gen-clang-attr-identifier-arg-list
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
SOURCE ../Basic/Attr.td
- TARGET ClangAttrExprArgs)
+ TARGET ClangAttrIdentifierArg)
clang_tablegen(AttrLateParsed.inc -gen-clang-attr-late-parsed-list
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
CLANG_LEVEL := ../../..
TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
-BUILT_SOURCES = AttrExprArgs.inc AttrLateParsed.inc
+BUILT_SOURCES = AttrIdentifierArg.inc AttrLateParsed.inc
TABLEGEN_INC_FILES_COMMON = 1
include $(CLANG_LEVEL)/Makefile
-$(ObjDir)/AttrExprArgs.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
+$(ObjDir)/AttrIdentifierArg.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
$(ObjDir)/.dir
- $(Echo) "Building Clang attribute expression arguments table with tblgen"
- $(Verb) $(ClangTableGen) -gen-clang-attr-expr-args-list -o $(call SYSPATH, $@) \
+ $(Echo) "Building Clang attribute identifier argument table with tblgen"
+ $(Verb) $(ClangTableGen) -gen-clang-attr-identifier-arg-list -o $(call SYSPATH, $@) \
-I $(PROJ_SRC_DIR)/../../ $<
$(ObjDir)/AttrLateParsed.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
$(ObjDir)/.dir
$(Echo) "Building Clang attribute late-parsed table with tblgen"
$(Verb) $(ClangTableGen) -gen-clang-attr-late-parsed-list -o $(call SYSPATH, $@) \
- -I $(PROJ_SRC_DIR)/../../ $<
\ No newline at end of file
+ -I $(PROJ_SRC_DIR)/../../ $<
add_dependencies(clangParse
ClangAttrClasses
- ClangAttrExprArgs
+ ClangAttrIdentifierArg
ClangAttrLateParsed
ClangAttrList
ClangAttrParsedAttrList
}
}
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
- SkipUntil(tok::r_paren, false);
+ SkipUntil(tok::r_paren);
SourceLocation Loc = Tok.getLocation();
- if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) {
- SkipUntil(tok::r_paren, false);
- }
+ if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
+ SkipUntil(tok::r_paren);
if (endLoc)
*endLoc = Loc;
}
}
-/// \brief Determine whether the given attribute has all expression arguments.
-static bool attributeHasExprArgs(const IdentifierInfo &II) {
- return llvm::StringSwitch<bool>(II.getName())
-#include "clang/Parse/AttrExprArgs.inc"
+/// \brief Determine whether the given attribute has an identifier argument.
+static bool attributeHasIdentifierArg(const IdentifierInfo &II) {
+ StringRef Name = II.getName();
+ if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
+ Name = Name.drop_front(2).drop_back(2);
+ return llvm::StringSwitch<bool>(Name)
+#include "clang/Parse/AttrIdentifierArg.inc"
.Default(false);
}
assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
+ AttributeList::Kind AttrKind =
+ AttributeList::getKind(AttrName, ScopeName, AttributeList::AS_GNU);
+
// Availability attributes have their own grammar.
- if (AttrName->isStr("availability")) {
+ if (AttrKind == AttributeList::AT_Availability) {
ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc);
return;
}
return;
}
// Type safety attributes have their own grammar.
- if (AttrName->isStr("type_tag_for_datatype")) {
+ if (AttrKind == AttributeList::AT_TypeTagForDatatype) {
ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc);
return;
}
- ConsumeParen(); // ignore the left paren loc for now
+ // Ignore the left paren location for now.
+ ConsumeParen();
bool BuiltinType = false;
ArgsVector ArgExprs;
break;
case tok::identifier: {
- if (AttrName->isStr("vec_type_hint")) {
+ if (AttrKind == AttributeList::AT_VecTypeHint) {
T = ParseTypeName(&TypeRange);
TypeParsed = true;
break;
}
- // If this attribute doesn't want an 'identifier' argument, then this
- // argument should be parsed as an expression.
- if (attributeHasExprArgs(*AttrName))
- break;
- ArgExprs.push_back(ParseIdentifierLoc());
+ // If this attribute wants an 'identifier' argument, make it so.
+ if (attributeHasIdentifierArg(*AttrName))
+ ArgExprs.push_back(ParseIdentifierLoc());
+
+ // __attribute__((iboutletcollection)) expects an identifier then
+ // some other (ignored) things.
+ if (AttrKind == AttributeList::AT_IBOutletCollection)
+ ArgExprs.push_back(ParseIdentifierLoc());
+
+ // If we don't know how to parse this attribute, but this is the only
+ // token in this argument, assume it's meant to be an identifier.
+ if (AttrKind == AttributeList::UnknownAttribute) {
+ const Token &Next = NextToken();
+ if (Next.is(tok::r_paren) || Next.is(tok::comma))
+ ArgExprs.push_back(ParseIdentifierLoc());
+ }
} break;
default:
bool isInvalid = false;
bool isParmType = false;
- if (!BuiltinType && !AttrName->isStr("vec_type_hint") &&
+ if (!BuiltinType && AttrKind != AttributeList::AT_VecTypeHint &&
(!ArgExprs.empty() ? Tok.is(tok::comma) : Tok.isNot(tok::r_paren))) {
// Eat the comma.
if (!ArgExprs.empty())
break;
ConsumeToken(); // Eat the comma, move to the next argument
}
- }
- else if (Tok.is(tok::less) && AttrName->isStr("iboutletcollection")) {
+ } else if (Tok.is(tok::less) &&
+ AttrKind == AttributeList::AT_IBOutletCollection) {
if (!ExpectAndConsume(tok::less, diag::err_expected_less_after, "<",
tok::greater)) {
while (Tok.is(tok::identifier)) {
Diag(Tok, diag::err_iboutletcollection_with_protocol);
SkipUntil(tok::r_paren, false, true); // skip until ')'
}
- } else if (AttrName->isStr("vec_type_hint")) {
+ } else if (AttrKind == AttributeList::AT_VecTypeHint) {
if (T.get() && !T.isInvalid())
isParmType = true;
else {
template <typename S> void X<S>::f() __attribute__((locks_excluded())); // expected-error{{nested name specifier 'X<S>::' for declaration does not refer into a class, class template or class template partial specialization}} \
// expected-warning{{attribute locks_excluded ignored, because it is not attached to a declaration}}
};
+
+namespace PR17666 {
+ const int A = 1;
+ typedef int __attribute__((__aligned__(A))) T1;
+ int check1[__alignof__(T1) == 1 ? 1 : -1];
+}
void foo32__() __attribute__((nomips16));
void foo32__() __attribute__((mips16));
-void foo32a() __attribute__((nomips16(xyz))) ; // expected-error {{'nomips16' attribute takes no arguments}}
-void __attribute__((mips16(xyz))) foo16a(); // expected-error {{'mips16' attribute takes no arguments}}
+void foo32a() __attribute__((nomips16(0))) ; // expected-error {{'nomips16' attribute takes no arguments}}
+void __attribute__((mips16(1))) foo16a(); // expected-error {{'mips16' attribute takes no arguments}}
void __attribute__((nomips16(1, 2))) foo32b(); // expected-error {{'nomips16' attribute takes no arguments}}
void __attribute__((mips16(1, 2))) foo16b(); // expected-error {{'mips16' attribute takes no arguments}}
OS << "#endif\n";
}
-// Emits the all-arguments-are-expressions property for attributes.
-void EmitClangAttrExprArgsList(RecordKeeper &Records, raw_ostream &OS) {
+static bool isIdentifierArgument(Record *Arg) {
+ return !Arg->getSuperClasses().empty() &&
+ llvm::StringSwitch<bool>(Arg->getSuperClasses().back()->getName())
+ .Case("IdentifierArgument", true)
+ .Case("EnumArgument", true)
+ .Default(false);
+}
+
+// Emits the first-argument-is-identifier property for attributes.
+void EmitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader("llvm::StringSwitch code to match attributes with "
- "expression arguments", OS);
+ "an identifier argument", OS);
std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
I != E; ++I) {
Record &Attr = **I;
- // Determine whether the first argument is something that is always
- // an expression.
+ // Determine whether the first argument is an identifier.
std::vector<Record *> Args = Attr.getValueAsListOfDefs("Args");
- if (Args.empty() || Args[0]->getSuperClasses().empty())
- continue;
-
- // Check whether this is one of the argument kinds that implies an
- // expression.
- // FIXME: Aligned is weird.
- if (!llvm::StringSwitch<bool>(Args[0]->getSuperClasses().back()->getName())
- .Case("AlignedArgument", true)
- .Case("BoolArgument", true)
- .Case("DefaultIntArgument", true)
- .Case("FunctionArgument", true)
- .Case("IntArgument", true)
- .Case("ExprArgument", true)
- .Case("StringArgument", true)
- .Case("UnsignedArgument", true)
- .Case("VariadicUnsignedArgument", true)
- .Case("VariadicExprArgument", true)
- .Default(false))
+ if (Args.empty() || !isIdentifierArgument(Args[0]))
continue;
+ // All these spellings take an identifier 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) {
- OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", "
- << "true" << ")\n";
+ if (Emitted.insert((*I)->getValueAsString("Name")).second)
+ OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", "
+ << "true" << ")\n";
}
}
}
enum ActionType {
GenClangAttrClasses,
- GenClangAttrExprArgsList,
+ GenClangAttrIdentifierArgList,
GenClangAttrImpl,
GenClangAttrList,
GenClangAttrPCHRead,
cl::values(
clEnumValN(GenClangAttrClasses, "gen-clang-attr-classes",
"Generate clang attribute clases"),
- clEnumValN(GenClangAttrExprArgsList, "gen-clang-attr-expr-args-list",
- "Generate a clang attribute expression "
- "arguments list"),
+ clEnumValN(GenClangAttrIdentifierArgList,
+ "gen-clang-attr-identifier-arg-list",
+ "Generate a list of attributes that take an "
+ "identifier as their first argument"),
clEnumValN(GenClangAttrImpl, "gen-clang-attr-impl",
"Generate clang attribute implementations"),
clEnumValN(GenClangAttrList, "gen-clang-attr-list",
clEnumValN(GenClangAttrTemplateInstantiate,
"gen-clang-attr-template-instantiate",
"Generate a clang template instantiate code"),
- clEnumValN(GenClangAttrParsedAttrList,
- "gen-clang-attr-parsed-attr-list",
- "Generate a clang parsed attribute list"),
- clEnumValN(GenClangAttrParsedAttrImpl,
- "gen-clang-attr-parsed-attr-impl",
- "Generate the clang parsed attribute helpers"),
- clEnumValN(GenClangAttrParsedAttrKinds,
- "gen-clang-attr-parsed-attr-kinds",
- "Generate a clang parsed attribute kinds"),
+ clEnumValN(GenClangAttrParsedAttrList,
+ "gen-clang-attr-parsed-attr-list",
+ "Generate a clang parsed attribute list"),
+ clEnumValN(GenClangAttrParsedAttrImpl,
+ "gen-clang-attr-parsed-attr-impl",
+ "Generate the clang parsed attribute helpers"),
+ clEnumValN(GenClangAttrParsedAttrKinds,
+ "gen-clang-attr-parsed-attr-kinds",
+ "Generate a clang parsed attribute kinds"),
clEnumValN(GenClangAttrDump, "gen-clang-attr-dump",
"Generate clang attribute dumper"),
clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
case GenClangAttrClasses:
EmitClangAttrClass(Records, OS);
break;
- case GenClangAttrExprArgsList:
- EmitClangAttrExprArgsList(Records, OS);
+ case GenClangAttrIdentifierArgList:
+ EmitClangAttrIdentifierArgList(Records, OS);
break;
case GenClangAttrImpl:
EmitClangAttrImpl(Records, OS);
const std::string &N, const std::string &S);
void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangAttrExprArgsList(RecordKeeper &Records, raw_ostream &OS);
+void EmitClangAttrIdentifierArgList(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);