summaryrefslogtreecommitdiffstats
path: root/clang/utils
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2013-05-02 23:08:12 +0000
committerDouglas Gregor <dgregor@apple.com>2013-05-02 23:08:12 +0000
commit44dff3f2dc2a0a6cc9e88552187730a2d7ea19bb (patch)
tree204ad94fb83dd6967988670370c098af9ccfbf88 /clang/utils
parent5705f546e54e94a07c83ef181efa307baef19dfe (diff)
downloadbcm5719-llvm-44dff3f2dc2a0a6cc9e88552187730a2d7ea19bb.tar.gz
bcm5719-llvm-44dff3f2dc2a0a6cc9e88552187730a2d7ea19bb.zip
Use attribute argument information to determine when to parse attribute arguments as expressions.
This change partly addresses a heinous problem we have with the parsing of attribute arguments that are a lone identifier. Previously, we would end up parsing the 'align' attribute of this as an expression "(Align)": template<unsigned Size, unsigned Align> class my_aligned_storage { __attribute__((align((Align)))) char storage[Size]; }; while this would parse as a "parameter name" 'Align': template<unsigned Size, unsigned Align> class my_aligned_storage { __attribute__((align(Align))) char storage[Size]; }; The code that handles the alignment attribute would completely ignore the parameter name, so the while the first of these would do what's expected, the second would silently be equivalent to template<unsigned Size, unsigned Align> class my_aligned_storage { __attribute__((align)) char storage[Size]; }; i.e., use the maximal alignment rather than the specified alignment. Address this by sniffing the "Args" provided in the TableGen description of attributes. If the first argument is "obviously" something that should be treated as an expression (rather than an identifier to be matched later), parse it as an expression. Fixes <rdar://problem/13700933>. llvm-svn: 180970
Diffstat (limited to 'clang/utils')
-rw-r--r--clang/utils/TableGen/ClangAttrEmitter.cpp43
-rw-r--r--clang/utils/TableGen/TableGen.cpp8
-rw-r--r--clang/utils/TableGen/TableGenBackends.h1
3 files changed, 52 insertions, 0 deletions
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index 7c8603fc6c3..36de06e2df6 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -971,6 +971,49 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
OS << "#endif\n";
}
+// Emits the LateParsed property for attributes.
+void EmitClangAttrExprArgsList(RecordKeeper &Records, raw_ostream &OS) {
+ emitSourceFileHeader("llvm::StringSwitch code to match attributes with "
+ "expression arguments", 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 something that is always
+ // an expression.
+ 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("IntArgument", true)
+ .Case("StringArgument", true)
+ .Case("ExprArgument", true)
+ .Case("UnsignedArgument", true)
+ .Case("VariadicUnsignedArgument", true)
+ .Case("VariadicExprArgument", true)
+ .Default(false))
+ continue;
+
+ std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
+
+ for (std::vector<Record*>::const_iterator I = Spellings.begin(),
+ E = Spellings.end(); I != E; ++I) {
+ OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", "
+ << "true" << ")\n";
+ }
+ }
+}
+
// Emits the class method definitions for attributes.
void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader("Attribute classes' member function definitions", OS);
diff --git a/clang/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp
index 3df8940b055..12e1c47725e 100644
--- a/clang/utils/TableGen/TableGen.cpp
+++ b/clang/utils/TableGen/TableGen.cpp
@@ -24,6 +24,7 @@ using namespace clang;
enum ActionType {
GenClangAttrClasses,
+ GenClangAttrExprArgsList,
GenClangAttrImpl,
GenClangAttrList,
GenClangAttrPCHRead,
@@ -62,6 +63,10 @@ namespace {
"Generate option parser implementation"),
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(GenClangAttrImpl, "gen-clang-attr-impl",
"Generate clang attribute implementations"),
clEnumValN(GenClangAttrList, "gen-clang-attr-list",
@@ -143,6 +148,9 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenClangAttrClasses:
EmitClangAttrClass(Records, OS);
break;
+ case GenClangAttrExprArgsList:
+ EmitClangAttrExprArgsList(Records, OS);
+ break;
case GenClangAttrImpl:
EmitClangAttrImpl(Records, OS);
break;
diff --git a/clang/utils/TableGen/TableGenBackends.h b/clang/utils/TableGen/TableGenBackends.h
index 03708b6a766..0ff33d775cc 100644
--- a/clang/utils/TableGen/TableGenBackends.h
+++ b/clang/utils/TableGen/TableGenBackends.h
@@ -30,6 +30,7 @@ void EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS,
const std::string &N, const std::string &S);
void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS);
+void EmitClangAttrExprArgsList(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