On Thu, May 2, 2013 at 4:25 PM, Douglas Gregor <[email protected]> wrote:
> Author: dgregor > Date: Thu May 2 18:25:32 2013 > New Revision: 180973 > > URL: http://llvm.org/viewvc/llvm-project?rev=180973&view=rev > Log: > 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>. > > > Modified: > cfe/trunk/include/clang/Parse/CMakeLists.txt > cfe/trunk/include/clang/Parse/Makefile > cfe/trunk/lib/Parse/CMakeLists.txt > cfe/trunk/lib/Parse/ParseDecl.cpp > cfe/trunk/lib/Sema/SemaDecl.cpp > cfe/trunk/test/SemaObjC/format-arg-attribute.m > cfe/trunk/test/SemaTemplate/attributes.cpp > cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp > cfe/trunk/utils/TableGen/TableGen.cpp > cfe/trunk/utils/TableGen/TableGenBackends.h > > Modified: cfe/trunk/include/clang/Parse/CMakeLists.txt > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/CMakeLists.txt?rev=180973&r1=180972&r2=180973&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Parse/CMakeLists.txt (original) > +++ cfe/trunk/include/clang/Parse/CMakeLists.txt Thu May 2 18:25:32 2013 > @@ -1,3 +1,8 @@ > +clang_tablegen(AttrExprArgs.inc -gen-clang-attr-expr-args-list > + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ > + SOURCE ../Basic/Attr.td > + TARGET ClangAttrExprArgs) > + > clang_tablegen(AttrLateParsed.inc -gen-clang-attr-late-parsed-list > -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ > SOURCE ../Basic/Attr.td > > Modified: cfe/trunk/include/clang/Parse/Makefile > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Makefile?rev=180973&r1=180972&r2=180973&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Parse/Makefile (original) > +++ cfe/trunk/include/clang/Parse/Makefile Thu May 2 18:25:32 2013 > @@ -1,11 +1,17 @@ > CLANG_LEVEL := ../../.. > TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic > -BUILT_SOURCES = AttrLateParsed.inc > +BUILT_SOURCES = AttrExprArgs.inc AttrLateParsed.inc > > TABLEGEN_INC_FILES_COMMON = 1 > > include $(CLANG_LEVEL)/Makefile > > +$(ObjDir)/AttrExprArgs.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, $@) \ > + -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" > > Modified: cfe/trunk/lib/Parse/CMakeLists.txt > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/CMakeLists.txt?rev=180973&r1=180972&r2=180973&view=diff > > ============================================================================== > --- cfe/trunk/lib/Parse/CMakeLists.txt (original) > +++ cfe/trunk/lib/Parse/CMakeLists.txt Thu May 2 18:25:32 2013 > @@ -17,6 +17,7 @@ add_clang_library(clangParse > > add_dependencies(clangParse > ClangAttrClasses > + ClangAttrExprArgs > ClangAttrLateParsed > ClangAttrList > ClangAttrParsedAttrList > > Modified: cfe/trunk/lib/Parse/ParseDecl.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=180973&r1=180972&r2=180973&view=diff > > ============================================================================== > --- cfe/trunk/lib/Parse/ParseDecl.cpp (original) > +++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu May 2 18:25:32 2013 > @@ -178,6 +178,12 @@ void Parser::ParseGNUAttributes(ParsedAt > } > } > > +/// \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(Ident > 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; > > Modified: cfe/trunk/lib/Sema/SemaDecl.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=180973&r1=180972&r2=180973&view=diff > > ============================================================================== > --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) > +++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu May 2 18:25:32 2013 > @@ -10633,8 +10633,8 @@ FieldDecl *Sema::CheckFieldDecl(Declarat > // 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); > > Modified: cfe/trunk/test/SemaObjC/format-arg-attribute.m > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/format-arg-attribute.m?rev=180973&r1=180972&r2=180973&view=diff > > ============================================================================== > --- cfe/trunk/test/SemaObjC/format-arg-attribute.m (original) > +++ cfe/trunk/test/SemaObjC/format-arg-attribute.m Thu May 2 18:25:32 2013 > @@ -14,7 +14,7 @@ union u1 { int i; } __attribute__((forma > enum e1 { E1V0 } __attribute__((format_arg(1))); // expected-warning > {{'format_arg' attribute only applies to functions}} > > extern NSString *ff3 (const NSString *) __attribute__((format_arg(3-2))); > -extern NSString *ff4 (const NSString *) __attribute__((format_arg(foo))); > // expected-error {{attribute takes one argument}} > +extern NSString *ff4 (const NSString *) __attribute__((format_arg(foo))); > // expected-error {{use of undeclared identifier 'foo'}} > > /* format_arg formats must take and return a string. */ > extern NSString *fi0 (int) __attribute__((format_arg(1))); // > expected-error {{format argument not a string type}} > > Modified: cfe/trunk/test/SemaTemplate/attributes.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/attributes.cpp?rev=180973&r1=180972&r2=180973&view=diff > > ============================================================================== > --- cfe/trunk/test/SemaTemplate/attributes.cpp (original) > +++ cfe/trunk/test/SemaTemplate/attributes.cpp Thu May 2 18:25:32 2013 > @@ -1,4 +1,4 @@ > -// RUN: %clang_cc1 -fsyntax-only -verify %s > +// RUN: %clang_cc1 -std=gnu++11 -fsyntax-only -verify %s > > namespace attribute_aligned { > template<int N> > @@ -18,6 +18,26 @@ namespace attribute_aligned { > check_alignment<2>::t c2; > check_alignment<3>::t c3; // expected-note 2 {{in instantiation}} > check_alignment<4>::t c4; > + > + template<unsigned Size, unsigned Align> > + class my_aligned_storage > + { > + __attribute__((align(Align))) char storage[Size]; > + }; > + > + template<typename T> > + class C { > + public: > + C() { > + static_assert(sizeof(t) == sizeof(T), "my_aligned_storage size > wrong"); > + static_assert(alignof(t) == alignof(T), "my_aligned_storage align > wrong"); // expected-warning{{'alignof' applied to an expression is a GNU > extension}} > + } > + > + private: > + my_aligned_storage<sizeof(T), alignof(T)> t; > + }; > + > + C<double> cd; > } > > namespace PR9049 { > > Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=180973&r1=180972&r2=180973&view=diff > > ============================================================================== > --- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original) > +++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Thu May 2 18:25:32 2013 > @@ -971,6 +971,48 @@ void EmitClangAttrClass(RecordKeeper &Re > OS << "#endif\n"; > } > > +// Emits the LateParsed property for attributes. > I don't believe you ;-) > +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("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); > > Modified: cfe/trunk/utils/TableGen/TableGen.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/TableGen.cpp?rev=180973&r1=180972&r2=180973&view=diff > > ============================================================================== > --- cfe/trunk/utils/TableGen/TableGen.cpp (original) > +++ cfe/trunk/utils/TableGen/TableGen.cpp Thu May 2 18:25:32 2013 > @@ -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, > case GenClangAttrClasses: > EmitClangAttrClass(Records, OS); > break; > + case GenClangAttrExprArgsList: > + EmitClangAttrExprArgsList(Records, OS); > + break; > case GenClangAttrImpl: > EmitClangAttrImpl(Records, OS); > break; > > Modified: cfe/trunk/utils/TableGen/TableGenBackends.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/TableGenBackends.h?rev=180973&r1=180972&r2=180973&view=diff > > ============================================================================== > --- cfe/trunk/utils/TableGen/TableGenBackends.h (original) > +++ cfe/trunk/utils/TableGen/TableGenBackends.h Thu May 2 18:25:32 2013 > @@ -30,6 +30,7 @@ void EmitClangASTNodes(RecordKeeper &RK, > 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); > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
