r180973 - Use attribute argument information to determine when to parse attribute arguments as expressions.

Richard Smith richard at metafoo.co.uk
Fri May 3 11:24:07 PDT 2013


On Thu, May 2, 2013 at 4:25 PM, Douglas Gregor <dgregor at apple.com> 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
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130503/5f1e792c/attachment.html>


More information about the cfe-commits mailing list