diff options
author | Douglas Gregor <dgregor@apple.com> | 2013-05-02 23:25:32 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2013-05-02 23:25:32 +0000 |
commit | d2472d4cdbee3c5ab5e5edfd080406a9f3a41a6e (patch) | |
tree | 6b18c9d8fcb70e5eb80a9703b447f2c969514e1e /clang/lib | |
parent | 33ebfe36e59dbc75a5f7ae28d59381ad478f460b (diff) | |
download | bcm5719-llvm-d2472d4cdbee3c5ab5e5edfd080406a9f3a41a6e.tar.gz bcm5719-llvm-d2472d4cdbee3c5ab5e5edfd080406a9f3a41a6e.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: 180973
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Parse/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 4 |
3 files changed, 13 insertions, 2 deletions
diff --git a/clang/lib/Parse/CMakeLists.txt b/clang/lib/Parse/CMakeLists.txt index 939998ecb1a..01c0694d035 100644 --- a/clang/lib/Parse/CMakeLists.txt +++ b/clang/lib/Parse/CMakeLists.txt @@ -17,6 +17,7 @@ add_clang_library(clangParse add_dependencies(clangParse ClangAttrClasses + ClangAttrExprArgs ClangAttrLateParsed ClangAttrList ClangAttrParsedAttrList diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 2f0c1a3b8da..a4cec8c2575 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/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; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 1aab5c669f9..cc8cb4a3951 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -10633,8 +10633,8 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, // FIXME: We need to pass in the attributes given an AST // representation, not a parser representation. if (D) { - // FIXME: What to pass instead of TUScope? - ProcessDeclAttributes(TUScope, NewFD, *D); + // FIXME: The current scope is almost... but not entirely... correct here. + ProcessDeclAttributes(getCurScope(), NewFD, *D); if (NewFD->hasAttrs()) CheckAlignasUnderalignment(NewFD); |