aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2013-05-02 23:25:32 +0000
committerDouglas Gregor <dgregor@apple.com>2013-05-02 23:25:32 +0000
commit92eb7d847cb1273a63d5e3b7dc98a7c97a81b703 (patch)
treed8a3fb34bb36933ecba4c0a8cc9b6b02c8dcf895 /lib/Parse
parentfa5f03052bc39d9c8f2fa8b4002597a8219760a4 (diff)
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>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@180973 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse')
-rw-r--r--lib/Parse/CMakeLists.txt1
-rw-r--r--lib/Parse/ParseDecl.cpp10
2 files changed, 11 insertions, 0 deletions
diff --git a/lib/Parse/CMakeLists.txt b/lib/Parse/CMakeLists.txt
index 939998ecb1..01c0694d03 100644
--- a/lib/Parse/CMakeLists.txt
+++ b/lib/Parse/CMakeLists.txt
@@ -17,6 +17,7 @@ add_clang_library(clangParse
add_dependencies(clangParse
ClangAttrClasses
+ ClangAttrExprArgs
ClangAttrLateParsed
ClangAttrList
ClangAttrParsedAttrList
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 2f0c1a3b8d..a4cec8c257 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -178,6 +178,12 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
}
}
+/// \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"
+ .Default(false);
+}
/// Parse the arguments to a parameterized GNU attribute or
/// a C++11 attribute in "gnu" namespace.
@@ -247,6 +253,10 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
TypeParsed = true;
break;
}
+ // If the attribute has all expression arguments, and not a "parameter",
+ // break out to handle it below.
+ if (attributeHasExprArgs(*AttrName))
+ break;
ParmName = Tok.getIdentifierInfo();
ParmLoc = ConsumeToken();
break;