r315856 - Add -f[no-]double-square-bracket-attributes as new driver options to control use of [[]] attributes in all language modes. This is the initial implementation of WG14 N2165, which is a proposal to add [[]] attributes to C2x, but also allows you to enable these attributes in C++98, or disable them in C++11 or later.

Galina Kistanova via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 18 11:19:06 PDT 2017


Thank you!

On Wed, Oct 18, 2017 at 7:38 AM, Aaron Ballman <aaron at aaronballman.com>
wrote:

> Thanks for pointing the breakage out -- it should be fixed with r316075.
>
> ~Aaron
>
> On Wed, Oct 18, 2017 at 7:50 AM, Aaron Ballman <aaron at aaronballman.com>
> wrote:
> > I'll take a look, thank you for pointing it out (and sorry for the
> trouble)!
> >
> > ~Aaron
> >
> > On Tue, Oct 17, 2017 at 9:56 PM, Galina Kistanova <gkistanova at gmail.com>
> wrote:
> >> Hello Aaron,
> >>
> >> This commit broke one our builders:
> >>
> >> http://lab.llvm.org:8011/builders/ubuntu-gcc7.1-werror/builds/2272
> >>
> >> . . .
> >> FAILED: /usr/local/gcc-7.1/bin/g++-7.1   -DGTEST_HAS_RTTI=0 -D_DEBUG
> >> -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS
> >> -D__STDC_LIMIT_MACROS -Itools/clang/lib/Basic
> >> -I/home/buildslave/am1i-slv2/ubuntu-gcc7.1-werror/llvm/
> tools/clang/lib/Basic
> >> -I/home/buildslave/am1i-slv2/ubuntu-gcc7.1-werror/llvm/
> tools/clang/include
> >> -Itools/clang/include -Iinclude
> >> -I/home/buildslave/am1i-slv2/ubuntu-gcc7.1-werror/llvm/include
> >> -Wno-noexcept-type -fPIC -fvisibility-inlines-hidden -Werror
> >> -Werror=date-time -std=c++11 -Wall -W -Wno-unused-parameter
> -Wwrite-strings
> >> -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long
> >> -Wno-maybe-uninitialized -Wdelete-non-virtual-dtor -Wno-comment
> >> -ffunction-sections -fdata-sections -fno-common -Woverloaded-virtual
> >> -fno-strict-aliasing -O3  -fPIC   -UNDEBUG  -fno-exceptions -fno-rtti
> -MD
> >> -MT tools/clang/lib/Basic/CMakeFiles/clangBasic.dir/Attributes.cpp.o
> -MF
> >> tools/clang/lib/Basic/CMakeFiles/clangBasic.dir/Attributes.cpp.o.d -o
> >> tools/clang/lib/Basic/CMakeFiles/clangBasic.dir/Attributes.cpp.o -c
> >> /home/buildslave/am1i-slv2/ubuntu-gcc7.1-werror/llvm/
> tools/clang/lib/Basic/Attributes.cpp
> >> In file included from
> >> /home/buildslave/am1i-slv2/ubuntu-gcc7.1-werror/llvm/
> tools/clang/lib/Basic/Attributes.cpp:15:0:
> >> tools/clang/include/clang/Basic/AttrHasAttributeImpl.inc: In function
> ‘int
> >> clang::hasAttribute(clang::AttrSyntax, const clang::IdentifierInfo*,
> const
> >> clang::IdentifierInfo*, const clang::TargetInfo&, const
> >> clang::LangOptions&)’:
> >> tools/clang/include/clang/Basic/AttrHasAttributeImpl.inc:526:8: error:
> this
> >> statement may fall through [-Werror=implicit-fallthrough=]
> >>  } else if (Scope->getName() == "gsl") {
> >>         ^~
> >> tools/clang/include/clang/Basic/AttrHasAttributeImpl.inc:532:1: note:
> here
> >>  case AttrSyntax::C: {
> >>  ^~~~
> >> cc1plus: all warnings being treated as errors
> >>
> >> Please have a look?
> >>
> >> Thanks
> >>
> >> Galina
> >>
> >> On Sun, Oct 15, 2017 at 8:01 AM, Aaron Ballman via cfe-commits
> >> <cfe-commits at lists.llvm.org> wrote:
> >>>
> >>> Author: aaronballman
> >>> Date: Sun Oct 15 08:01:42 2017
> >>> New Revision: 315856
> >>>
> >>> URL: http://llvm.org/viewvc/llvm-project?rev=315856&view=rev
> >>> Log:
> >>> Add -f[no-]double-square-bracket-attributes as new driver options to
> >>> control use of [[]] attributes in all language modes. This is the
> initial
> >>> implementation of WG14 N2165, which is a proposal to add [[]]
> attributes to
> >>> C2x, but also allows you to enable these attributes in C++98, or
> disable
> >>> them in C++11 or later.
> >>>
> >>> Added:
> >>>     cfe/trunk/test/Misc/ast-dump-c-attr.c
> >>>     cfe/trunk/test/Parser/c2x-attributes.c
> >>>     cfe/trunk/test/Parser/c2x-attributes.m
> >>>     cfe/trunk/test/Sema/attr-deprecated-c2x.c
> >>> Modified:
> >>>     cfe/trunk/include/clang/Basic/Attr.td
> >>>     cfe/trunk/include/clang/Basic/Attributes.h
> >>>     cfe/trunk/include/clang/Basic/LangOptions.def
> >>>     cfe/trunk/include/clang/Driver/Options.td
> >>>     cfe/trunk/include/clang/Parse/Parser.h
> >>>     cfe/trunk/include/clang/Sema/AttributeList.h
> >>>     cfe/trunk/lib/Frontend/CompilerInvocation.cpp
> >>>     cfe/trunk/lib/Lex/Lexer.cpp
> >>>     cfe/trunk/lib/Parse/ParseDecl.cpp
> >>>     cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> >>>     cfe/trunk/lib/Sema/AttributeList.cpp
> >>>     cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
> >>>
> >>> Modified: cfe/trunk/include/clang/Basic/Attr.td
> >>> URL:
> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Basic/Attr.td?rev=315856&r1=315855&r2=315856&view=diff
> >>>
> >>> ============================================================
> ==================
> >>> --- cfe/trunk/include/clang/Basic/Attr.td (original)
> >>> +++ cfe/trunk/include/clang/Basic/Attr.td Sun Oct 15 08:01:42 2017
> >>> @@ -210,6 +210,10 @@ class CXX11<string namespace, string nam
> >>>    string Namespace = namespace;
> >>>    int Version = version;
> >>>  }
> >>> +class C2x<string namespace, string name> : Spelling<name, "C2x"> {
> >>> +  string Namespace = namespace;
> >>> +}
> >>> +
> >>>  class Keyword<string name> : Spelling<name, "Keyword">;
> >>>  class Pragma<string namespace, string name> : Spelling<name,
> "Pragma"> {
> >>>    string Namespace = namespace;
> >>> @@ -958,7 +962,7 @@ def RenderScriptKernel : Attr {
> >>>
> >>>  def Deprecated : InheritableAttr {
> >>>    let Spellings = [GCC<"deprecated">, Declspec<"deprecated">,
> >>> -                   CXX11<"","deprecated", 201309>];
> >>> +                   CXX11<"","deprecated", 201309>, C2x<"",
> >>> "deprecated">];
> >>>    let Args = [StringArgument<"Message", 1>,
> >>>                // An optional string argument that enables us to
> provide a
> >>>                // Fix-It.
> >>>
> >>> Modified: cfe/trunk/include/clang/Basic/Attributes.h
> >>> URL:
> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Basic/Attributes.h?rev=315856&r1=315855&r2=315856&view=diff
> >>>
> >>> ============================================================
> ==================
> >>> --- cfe/trunk/include/clang/Basic/Attributes.h (original)
> >>> +++ cfe/trunk/include/clang/Basic/Attributes.h Sun Oct 15 08:01:42
> 2017
> >>> @@ -26,6 +26,8 @@ enum class AttrSyntax {
> >>>    Microsoft,
> >>>    // Is the identifier known as a C++-style attribute?
> >>>    CXX,
> >>> +  // Is the identifier known as a C-style attribute?
> >>> +  C,
> >>>    // Is the identifier known as a pragma attribute?
> >>>    Pragma
> >>>  };
> >>>
> >>> Modified: cfe/trunk/include/clang/Basic/LangOptions.def
> >>> URL:
> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Basic/LangOptions.def?rev=315856&r1=315855&r2=315856&view=diff
> >>>
> >>> ============================================================
> ==================
> >>> --- cfe/trunk/include/clang/Basic/LangOptions.def (original)
> >>> +++ cfe/trunk/include/clang/Basic/LangOptions.def Sun Oct 15 08:01:42
> 2017
> >>> @@ -137,6 +137,8 @@ LANGOPT(GNUAsm            , 1, 1, "GNU-s
> >>>  LANGOPT(CoroutinesTS      , 1, 0, "C++ coroutines TS")
> >>>  LANGOPT(RelaxedTemplateTemplateArgs, 1, 0, "C++17 relaxed matching of
> >>> template template arguments")
> >>>
> >>> +LANGOPT(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes
> extension
> >>> for all language standard modes")
> >>> +
> >>>  BENIGN_LANGOPT(ThreadsafeStatics , 1, 1, "thread-safe static
> >>> initializers")
> >>>  LANGOPT(POSIXThreads      , 1, 0, "POSIX thread support")
> >>>  LANGOPT(Blocks            , 1, 0, "blocks extension to C")
> >>>
> >>> Modified: cfe/trunk/include/clang/Driver/Options.td
> >>> URL:
> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Driver/Options.td?rev=315856&r1=315855&r2=315856&view=diff
> >>>
> >>> ============================================================
> ==================
> >>> --- cfe/trunk/include/clang/Driver/Options.td (original)
> >>> +++ cfe/trunk/include/clang/Driver/Options.td Sun Oct 15 08:01:42 2017
> >>> @@ -606,6 +606,13 @@ def fastf : Flag<["-"], "fastf">, Group<
> >>>  def fast : Flag<["-"], "fast">, Group<f_Group>;
> >>>  def fasynchronous_unwind_tables : Flag<["-"],
> >>> "fasynchronous-unwind-tables">, Group<f_Group>;
> >>>
> >>> +def fdouble_square_bracket_attributes : Flag<[ "-" ],
> >>> "fdouble-square-bracket-attributes">,
> >>> +  Group<f_Group>, Flags<[DriverOption, CC1Option]>,
> >>> +  HelpText<"Enable '[[]]' attributes in all C and C++ language
> modes">;
> >>> +def fno_double_square_bracket_attributes : Flag<[ "-" ],
> >>> "fno-fdouble-square-bracket-attributes">,
> >>> +  Group<f_Group>, Flags<[DriverOption]>,
> >>> +  HelpText<"Disable '[[]]' attributes in all C and C++ language
> modes">;
> >>> +
> >>>  def fautolink : Flag <["-"], "fautolink">, Group<f_Group>;
> >>>  def fno_autolink : Flag <["-"], "fno-autolink">, Group<f_Group>,
> >>>    Flags<[DriverOption, CC1Option]>,
> >>>
> >>> Modified: cfe/trunk/include/clang/Parse/Parser.h
> >>> URL:
> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Parse/Parser.h?rev=315856&r1=315855&r2=315856&view=diff
> >>>
> >>> ============================================================
> ==================
> >>> --- cfe/trunk/include/clang/Parse/Parser.h (original)
> >>> +++ cfe/trunk/include/clang/Parse/Parser.h Sun Oct 15 08:01:42 2017
> >>> @@ -2163,18 +2163,25 @@ public:
> >>>  private:
> >>>    void ParseBlockId(SourceLocation CaretLoc);
> >>>
> >>> -  // Check for the start of a C++11 attribute-specifier-seq in a
> context
> >>> where
> >>> -  // an attribute is not allowed.
> >>> +  /// Are [[]] attributes enabled?
> >>> +  bool standardAttributesAllowed() const {
> >>> +    const LangOptions &LO = getLangOpts();
> >>> +    return LO.DoubleSquareBracketAttributes;
> >>> +  }
> >>> +
> >>> +  // Check for the start of an attribute-specifier-seq in a context
> where
> >>> an
> >>> +  // attribute is not allowed.
> >>>    bool CheckProhibitedCXX11Attribute() {
> >>>      assert(Tok.is(tok::l_square));
> >>> -    if (!getLangOpts().CPlusPlus11 || NextToken().isNot(tok::l_
> square))
> >>> +    if (!standardAttributesAllowed() || NextToken().isNot(tok::l_
> square))
> >>>        return false;
> >>>      return DiagnoseProhibitedCXX11Attribute();
> >>>    }
> >>> +
> >>>    bool DiagnoseProhibitedCXX11Attribute();
> >>>    void CheckMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs,
> >>>                                      SourceLocation CorrectLocation) {
> >>> -    if (!getLangOpts().CPlusPlus11)
> >>> +    if (!standardAttributesAllowed())
> >>>        return;
> >>>      if ((Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square))
> &&
> >>>          Tok.isNot(tok::kw_alignas))
> >>> @@ -2194,17 +2201,18 @@ private:
> >>>    }
> >>>    void DiagnoseProhibitedAttributes(ParsedAttributesWithRange
> &attrs);
> >>>
> >>> -  // Forbid C++11 attributes that appear on certain syntactic
> >>> -  // locations which standard permits but we don't supported yet,
> >>> -  // for example, attributes appertain to decl specifiers.
> >>> +  // Forbid C++11 and C2x attributes that appear on certain syntactic
> >>> locations
> >>> +  // which standard permits but we don't supported yet, for example,
> >>> attributes
> >>> +  // appertain to decl specifiers.
> >>>    void ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs,
> >>>                                 unsigned DiagID);
> >>>
> >>> -  /// \brief Skip C++11 attributes and return the end location of the
> >>> last one.
> >>> +  /// \brief Skip C++11 and C2x attributes and return the end
> location of
> >>> the
> >>> +  /// last one.
> >>>    /// \returns SourceLocation() if there are no attributes.
> >>>    SourceLocation SkipCXX11Attributes();
> >>>
> >>> -  /// \brief Diagnose and skip C++11 attributes that appear in
> syntactic
> >>> +  /// \brief Diagnose and skip C++11 and C2x attributes that appear in
> >>> syntactic
> >>>    /// locations where attributes are not allowed.
> >>>    void DiagnoseAndSkipCXX11Attributes();
> >>>
> >>> @@ -2254,7 +2262,7 @@ private:
> >>>                            AttributeList::Syntax Syntax);
> >>>
> >>>    void MaybeParseCXX11Attributes(Declarator &D) {
> >>> -    if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) {
> >>> +    if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) {
> >>>        ParsedAttributesWithRange attrs(AttrFactory);
> >>>        SourceLocation endLoc;
> >>>        ParseCXX11Attributes(attrs, &endLoc);
> >>> @@ -2263,7 +2271,7 @@ private:
> >>>    }
> >>>    void MaybeParseCXX11Attributes(ParsedAttributes &attrs,
> >>>                                   SourceLocation *endLoc = nullptr) {
> >>> -    if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) {
> >>> +    if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) {
> >>>        ParsedAttributesWithRange attrsWithRange(AttrFactory);
> >>>        ParseCXX11Attributes(attrsWithRange, endLoc);
> >>>        attrs.takeAllFrom(attrsWithRange);
> >>> @@ -2272,8 +2280,8 @@ private:
> >>>    void MaybeParseCXX11Attributes(ParsedAttributesWithRange &attrs,
> >>>                                   SourceLocation *endLoc = nullptr,
> >>>                                   bool OuterMightBeMessageSend =
> false) {
> >>> -    if (getLangOpts().CPlusPlus11 &&
> >>> -        isCXX11AttributeSpecifier(false, OuterMightBeMessageSend))
> >>> +    if (standardAttributesAllowed() &&
> >>> +      isCXX11AttributeSpecifier(false, OuterMightBeMessageSend))
> >>>        ParseCXX11Attributes(attrs, endLoc);
> >>>    }
> >>>
> >>> @@ -2281,8 +2289,8 @@ private:
> >>>                                      SourceLocation *EndLoc = nullptr);
> >>>    void ParseCXX11Attributes(ParsedAttributesWithRange &attrs,
> >>>                              SourceLocation *EndLoc = nullptr);
> >>> -  /// \brief Parses a C++-style attribute argument list. Returns true
> if
> >>> this
> >>> -  /// results in adding an attribute to the ParsedAttributes list.
> >>> +  /// \brief Parses a C++11 (or C2x)-style attribute argument list.
> >>> Returns true
> >>> +  /// if this results in adding an attribute to the ParsedAttributes
> >>> list.
> >>>    bool ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
> >>>                                 SourceLocation AttrNameLoc,
> >>>                                 ParsedAttributes &Attrs, SourceLocation
> >>> *EndLoc,
> >>>
> >>> Modified: cfe/trunk/include/clang/Sema/AttributeList.h
> >>> URL:
> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Sema/AttributeList.h?rev=315856&r1=315855&r2=315856&view=diff
> >>>
> >>> ============================================================
> ==================
> >>> --- cfe/trunk/include/clang/Sema/AttributeList.h (original)
> >>> +++ cfe/trunk/include/clang/Sema/AttributeList.h Sun Oct 15 08:01:42
> 2017
> >>> @@ -100,6 +100,8 @@ public:
> >>>      AS_GNU,
> >>>      /// [[...]]
> >>>      AS_CXX11,
> >>> +    /// [[...]]
> >>> +    AS_C2x,
> >>>      /// __declspec(...)
> >>>      AS_Declspec,
> >>>      /// [uuid("...")] class Foo
> >>> @@ -378,6 +380,9 @@ public:
> >>>    bool isCXX11Attribute() const {
> >>>      return SyntaxUsed == AS_CXX11 || isAlignasAttribute();
> >>>    }
> >>> +  bool isC2xAttribute() const {
> >>> +    return SyntaxUsed == AS_C2x;
> >>> +  }
> >>>    bool isKeywordAttribute() const {
> >>>      return SyntaxUsed == AS_Keyword || SyntaxUsed ==
> >>> AS_ContextSensitiveKeyword;
> >>>    }
> >>>
> >>> Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
> >>> URL:
> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/
> Frontend/CompilerInvocation.cpp?rev=315856&r1=315855&r2=315856&view=diff
> >>>
> >>> ============================================================
> ==================
> >>> --- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
> >>> +++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Sun Oct 15 08:01:42
> 2017
> >>> @@ -2138,6 +2138,12 @@ static void ParseLangArgs(LangOptions &O
> >>>      && Opts.OpenCLVersion >= 200);
> >>>    Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_
> runtime_optional);
> >>>    Opts.CoroutinesTS = Args.hasArg(OPT_fcoroutines_ts);
> >>> +
> >>> +  // Enable [[]] attributes in C++11 by default.
> >>> +  Opts.DoubleSquareBracketAttributes =
> >>> +      Args.hasFlag(OPT_fdouble_square_bracket_attributes,
> >>> +                   OPT_fno_double_square_bracket_attributes,
> >>> Opts.CPlusPlus11);
> >>> +
> >>>    Opts.ModulesTS = Args.hasArg(OPT_fmodules_ts);
> >>>    Opts.Modules = Args.hasArg(OPT_fmodules) || Opts.ModulesTS;
> >>>    Opts.ModulesStrictDeclUse = Args.hasArg(OPT_fmodules_
> strict_decluse);
> >>>
> >>> Modified: cfe/trunk/lib/Lex/Lexer.cpp
> >>> URL:
> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/
> Lexer.cpp?rev=315856&r1=315855&r2=315856&view=diff
> >>>
> >>> ============================================================
> ==================
> >>> --- cfe/trunk/lib/Lex/Lexer.cpp (original)
> >>> +++ cfe/trunk/lib/Lex/Lexer.cpp Sun Oct 15 08:01:42 2017
> >>> @@ -3612,7 +3612,9 @@ LexNextToken:
> >>>      if (LangOpts.Digraphs && Char == '>') {
> >>>        Kind = tok::r_square; // ':>' -> ']'
> >>>        CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
> >>> -    } else if (LangOpts.CPlusPlus && Char == ':') {
> >>> +    } else if ((LangOpts.CPlusPlus ||
> >>> +                LangOpts.DoubleSquareBracketAttributes) &&
> >>> +               Char == ':') {
> >>>        Kind = tok::coloncolon;
> >>>        CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
> >>>      } else {
> >>>
> >>> Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
> >>> URL:
> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/
> ParseDecl.cpp?rev=315856&r1=315855&r2=315856&view=diff
> >>>
> >>> ============================================================
> ==================
> >>> --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
> >>> +++ cfe/trunk/lib/Parse/ParseDecl.cpp Sun Oct 15 08:01:42 2017
> >>> @@ -1562,7 +1562,7 @@ void Parser::DiagnoseProhibitedAttribute
> >>>  void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange
> &Attrs,
> >>>                                       unsigned DiagID) {
> >>>    for (AttributeList *Attr = Attrs.getList(); Attr; Attr =
> >>> Attr->getNext()) {
> >>> -    if (!Attr->isCXX11Attribute())
> >>> +    if (!Attr->isCXX11Attribute() && !Attr->isC2xAttribute())
> >>>        continue;
> >>>      if (Attr->getKind() == AttributeList::UnknownAttribute)
> >>>        Diag(Attr->getLoc(), diag::warn_unknown_attribute_ignored)
> >>> @@ -2925,7 +2925,7 @@ void Parser::ParseDeclarationSpecifiers(
> >>>
> >>>      case tok::l_square:
> >>>      case tok::kw_alignas:
> >>> -      if (!getLangOpts().CPlusPlus11 || !isCXX11AttributeSpecifier())
> >>> +      if (!standardAttributesAllowed() ||
> !isCXX11AttributeSpecifier())
> >>>          goto DoneWithDeclSpec;
> >>>
> >>>        ProhibitAttributes(attrs);
> >>> @@ -3778,7 +3778,8 @@ void Parser::ParseDeclarationSpecifiers(
> >>>  /// semicolon.
> >>>  ///
> >>>  ///       struct-declaration:
> >>> -///         specifier-qualifier-list struct-declarator-list
> >>> +/// [C2x]   attributes-specifier-seq[opt]
> >>> +///           specifier-qualifier-list struct-declarator-list
> >>>  /// [GNU]   __extension__ struct-declaration
> >>>  /// [GNU]   specifier-qualifier-list
> >>>  ///       struct-declarator-list:
> >>> @@ -3802,6 +3803,11 @@ void Parser::ParseStructDeclaration(
> >>>      return ParseStructDeclaration(DS, FieldsCallback);
> >>>    }
> >>>
> >>> +  // Parse leading attributes.
> >>> +  ParsedAttributesWithRange Attrs(AttrFactory);
> >>> +  MaybeParseCXX11Attributes(Attrs);
> >>> +  DS.takeAttributesFrom(Attrs);
> >>> +
> >>>    // Parse the common specifier-qualifiers-list piece.
> >>>    ParseSpecifierQualifierList(DS);
> >>>
> >>> @@ -4412,11 +4418,12 @@ void Parser::ParseEnumBody(SourceLocatio
> >>>      ParsedAttributesWithRange attrs(AttrFactory);
> >>>      MaybeParseGNUAttributes(attrs);
> >>>      ProhibitAttributes(attrs); // GNU-style attributes are prohibited.
> >>> -    if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) {
> >>> -      Diag(Tok.getLocation(), getLangOpts().CPlusPlus1z
> >>> -                                  ?
> >>> diag::warn_cxx14_compat_ns_enum_attribute
> >>> -                                  : diag::ext_ns_enum_attribute)
> >>> -        << 1 /*enumerator*/;
> >>> +    if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) {
> >>> +      if (getLangOpts().CPlusPlus)
> >>> +        Diag(Tok.getLocation(), getLangOpts().CPlusPlus1z
> >>> +                                    ?
> >>> diag::warn_cxx14_compat_ns_enum_attribute
> >>> +                                    : diag::ext_ns_enum_attribute)
> >>> +            << 1 /*enumerator*/;
> >>>        ParseCXX11Attributes(attrs);
> >>>      }
> >>>
> >>> @@ -5025,7 +5032,7 @@ void Parser::ParseTypeQualifierListOpt(
> >>>      DeclSpec &DS, unsigned AttrReqs, bool AtomicAllowed,
> >>>      bool IdentifierRequired,
> >>>      Optional<llvm::function_ref<void()>> CodeCompletionHandler) {
> >>> -  if (getLangOpts().CPlusPlus11 && (AttrReqs &
> AR_CXX11AttributesParsed)
> >>> &&
> >>> +  if (standardAttributesAllowed() && (AttrReqs &
> >>> AR_CXX11AttributesParsed) &&
> >>>        isCXX11AttributeSpecifier()) {
> >>>      ParsedAttributesWithRange attrs(AttrFactory);
> >>>      ParseCXX11Attributes(attrs);
> >>> @@ -5962,7 +5969,7 @@ void Parser::ParseFunctionDeclarator(Dec
> >>>    SmallVector<SourceRange, 2> DynamicExceptionRanges;
> >>>    ExprResult NoexceptExpr;
> >>>    CachedTokens *ExceptionSpecTokens = nullptr;
> >>> -  ParsedAttributes FnAttrs(AttrFactory);
> >>> +  ParsedAttributesWithRange FnAttrs(AttrFactory);
> >>>    TypeResult TrailingReturnType;
> >>>
> >>>    /* LocalEndLoc is the end location for the local FunctionTypeLoc.
> >>> @@ -5983,6 +5990,11 @@ void Parser::ParseFunctionDeclarator(Dec
> >>>      RParenLoc = Tracker.getCloseLocation();
> >>>      LocalEndLoc = RParenLoc;
> >>>      EndLoc = RParenLoc;
> >>> +
> >>> +    // If there are attributes following the identifier list, parse
> them
> >>> and
> >>> +    // prohibit them.
> >>> +    MaybeParseCXX11Attributes(FnAttrs);
> >>> +    ProhibitAttributes(FnAttrs);
> >>>    } else {
> >>>      if (Tok.isNot(tok::r_paren))
> >>>        ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo,
> >>> @@ -6089,6 +6101,8 @@ void Parser::ParseFunctionDeclarator(Dec
> >>>          TrailingReturnType = ParseTrailingReturnType(Range);
> >>>          EndLoc = Range.getEnd();
> >>>        }
> >>> +    } else if (standardAttributesAllowed()) {
> >>> +      MaybeParseCXX11Attributes(FnAttrs);
> >>>      }
> >>>    }
> >>>
> >>>
> >>> Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> >>> URL:
> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/
> ParseDeclCXX.cpp?rev=315856&r1=315855&r2=315856&view=diff
> >>>
> >>> ============================================================
> ==================
> >>> --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
> >>> +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sun Oct 15 08:01:42 2017
> >>> @@ -3814,7 +3814,7 @@ IdentifierInfo *Parser::TryParseCXX11Att
> >>>  }
> >>>
> >>>  static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo
> *AttrName,
> >>> -                                               IdentifierInfo
> *ScopeName)
> >>> {
> >>> +                                              IdentifierInfo
> *ScopeName)
> >>> {
> >>>    switch (AttributeList::getKind(AttrName, ScopeName,
> >>>                                   AttributeList::AS_CXX11)) {
> >>>    case AttributeList::AT_CarriesDependency:
> >>> @@ -3853,11 +3853,14 @@ bool Parser::ParseCXX11AttributeArgs(Ide
> >>>                                       SourceLocation ScopeLoc) {
> >>>    assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument
> list");
> >>>    SourceLocation LParenLoc = Tok.getLocation();
> >>> +  const LangOptions &LO = getLangOpts();
> >>> +  AttributeList::Syntax Syntax =
> >>> +      LO.CPlusPlus ? AttributeList::AS_CXX11 : AttributeList::AS_C2x;
> >>>
> >>>    // If the attribute isn't known, we will not attempt to parse any
> >>>    // arguments.
> >>> -  if (!hasAttribute(AttrSyntax::CXX, ScopeName, AttrName,
> >>> -                    getTargetInfo(), getLangOpts())) {
> >>> +  if (!hasAttribute(LO.CPlusPlus ? AttrSyntax::CXX : AttrSyntax::C,
> >>> ScopeName,
> >>> +                    AttrName, getTargetInfo(), getLangOpts())) {
> >>>      // Eat the left paren, then skip to the ending right paren.
> >>>      ConsumeParen();
> >>>      SkipUntil(tok::r_paren);
> >>> @@ -3868,7 +3871,7 @@ bool Parser::ParseCXX11AttributeArgs(Ide
> >>>      // GNU-scoped attributes have some special cases to handle
> >>> GNU-specific
> >>>      // behaviors.
> >>>      ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc,
> >>> ScopeName,
> >>> -                          ScopeLoc, AttributeList::AS_CXX11, nullptr);
> >>> +                          ScopeLoc, Syntax, nullptr);
> >>>      return true;
> >>>    }
> >>>
> >>> @@ -3877,11 +3880,11 @@ bool Parser::ParseCXX11AttributeArgs(Ide
> >>>    if (ScopeName && ScopeName->getName() == "clang")
> >>>      NumArgs =
> >>>          ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc,
> >>> ScopeName,
> >>> -                                ScopeLoc, AttributeList::AS_CXX11);
> >>> +                                ScopeLoc, Syntax);
> >>>    else
> >>>      NumArgs =
> >>>          ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs,
> EndLoc,
> >>> -                                 ScopeName, ScopeLoc,
> >>> AttributeList::AS_CXX11);
> >>> +                                 ScopeName, ScopeLoc, Syntax);
> >>>
> >>>    const AttributeList *Attr = Attrs.getList();
> >>>    if (Attr && IsBuiltInOrStandardCXX11Attribute(AttrName,
> ScopeName)) {
> >>> @@ -3907,7 +3910,7 @@ bool Parser::ParseCXX11AttributeArgs(Ide
> >>>    return true;
> >>>  }
> >>>
> >>> -/// ParseCXX11AttributeSpecifier - Parse a C++11 attribute-specifier.
> >>> +/// ParseCXX11AttributeSpecifier - Parse a C++11 or C2x
> >>> attribute-specifier.
> >>>  ///
> >>>  /// [C++11] attribute-specifier:
> >>>  ///         '[' '[' attribute-list ']' ']'
> >>> @@ -3939,8 +3942,8 @@ void Parser::ParseCXX11AttributeSpecifie
> >>>      return;
> >>>    }
> >>>
> >>> -  assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square)
> >>> -      && "Not a C++11 attribute list");
> >>> +  assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square) &&
> >>> +         "Not a double square bracket attribute list");
> >>>
> >>>    Diag(Tok.getLocation(), diag::warn_cxx98_compat_attribute);
> >>>
> >>> @@ -4016,10 +4019,12 @@ void Parser::ParseCXX11AttributeSpecifie
> >>>                                             ScopeName, ScopeLoc);
> >>>
> >>>      if (!AttrParsed)
> >>> -      attrs.addNew(AttrName,
> >>> -                   SourceRange(ScopeLoc.isValid() ? ScopeLoc :
> AttrLoc,
> >>> -                               AttrLoc),
> >>> -                   ScopeName, ScopeLoc, nullptr, 0,
> >>> AttributeList::AS_CXX11);
> >>> +      attrs.addNew(
> >>> +          AttrName,
> >>> +          SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc,
> AttrLoc),
> >>> +          ScopeName, ScopeLoc, nullptr, 0,
> >>> +          getLangOpts().CPlusPlus ? AttributeList::AS_CXX11
> >>> +                                  : AttributeList::AS_C2x);
> >>>
> >>>      if (TryConsumeToken(tok::ellipsis))
> >>>        Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis)
> >>> @@ -4034,13 +4039,13 @@ void Parser::ParseCXX11AttributeSpecifie
> >>>      SkipUntil(tok::r_square);
> >>>  }
> >>>
> >>> -/// ParseCXX11Attributes - Parse a C++11 attribute-specifier-seq.
> >>> +/// ParseCXX11Attributes - Parse a C++11 or C2x
> attribute-specifier-seq.
> >>>  ///
> >>>  /// attribute-specifier-seq:
> >>>  ///       attribute-specifier-seq[opt] attribute-specifier
> >>>  void Parser::ParseCXX11Attributes(ParsedAttributesWithRange &attrs,
> >>>                                    SourceLocation *endLoc) {
> >>> -  assert(getLangOpts().CPlusPlus11);
> >>> +  assert(standardAttributesAllowed());
> >>>
> >>>    SourceLocation StartLoc = Tok.getLocation(), Loc;
> >>>    if (!endLoc)
> >>>
> >>> Modified: cfe/trunk/lib/Sema/AttributeList.cpp
> >>> URL:
> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> AttributeList.cpp?rev=315856&r1=315855&r2=315856&view=diff
> >>>
> >>> ============================================================
> ==================
> >>> --- cfe/trunk/lib/Sema/AttributeList.cpp (original)
> >>> +++ cfe/trunk/lib/Sema/AttributeList.cpp Sun Oct 15 08:01:42 2017
> >>> @@ -114,7 +114,8 @@ static StringRef normalizeAttrName(Strin
> >>>    // Normalize the attribute name, __foo__ becomes foo. This is only
> >>> allowable
> >>>    // for GNU attributes.
> >>>    bool IsGNU = SyntaxUsed == AttributeList::AS_GNU ||
> >>> -               (SyntaxUsed == AttributeList::AS_CXX11 && ScopeName ==
> >>> "gnu");
> >>> +               ((SyntaxUsed == AttributeList::AS_CXX11 ||
> >>> +                SyntaxUsed == AttributeList::AS_C2x) && ScopeName ==
> >>> "gnu");
> >>>    if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") &&
> >>>        AttrName.endswith("__"))
> >>>      AttrName = AttrName.slice(2, AttrName.size() - 2);
> >>> @@ -135,7 +136,7 @@ AttributeList::Kind AttributeList::getKi
> >>>
> >>>    // Ensure that in the case of C++11 attributes, we look for '::foo'
> if
> >>> it is
> >>>    // unscoped.
> >>> -  if (ScopeName || SyntaxUsed == AS_CXX11)
> >>> +  if (ScopeName || SyntaxUsed == AS_CXX11 || SyntaxUsed == AS_C2x)
> >>>      FullName += "::";
> >>>    FullName += AttrName;
> >>>
> >>>
> >>> Added: cfe/trunk/test/Misc/ast-dump-c-attr.c
> >>> URL:
> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/
> ast-dump-c-attr.c?rev=315856&view=auto
> >>>
> >>> ============================================================
> ==================
> >>> --- cfe/trunk/test/Misc/ast-dump-c-attr.c (added)
> >>> +++ cfe/trunk/test/Misc/ast-dump-c-attr.c Sun Oct 15 08:01:42 2017
> >>> @@ -0,0 +1,46 @@
> >>> +// RUN: %clang_cc1 -triple x86_64-pc-linux
> >>> -fdouble-square-bracket-attributes -Wno-deprecated-declarations
> -ast-dump
> >>> -ast-dump-filter Test %s | FileCheck --strict-whitespace %s
> >>> +
> >>> +int Test1 [[deprecated]];
> >>> +// CHECK:      VarDecl{{.*}}Test1
> >>> +// CHECK-NEXT:   DeprecatedAttr 0x{{[^ ]*}} <col:13> "" ""
> >>> +
> >>> +enum [[deprecated("Frobble")]] Test2 {
> >>> +  Test3 [[deprecated]]
> >>> +};
> >>> +// CHECK:      EnumDecl{{.*}}Test2
> >>> +// CHECK-NEXT:   DeprecatedAttr 0x{{[^ ]*}} <col:8, col:28> "Frobble"
> ""
> >>> +// CHECK-NEXT:   EnumConstantDecl{{.*}}Test3
> >>> +// CHECK-NEXT:     DeprecatedAttr 0x{{[^ ]*}} <col:11> "" ""
> >>> +
> >>> +struct [[deprecated]] Test4 {
> >>> +  [[deprecated("Frobble")]] int Test5, Test6;
> >>> +  int Test7 [[deprecated]] : 12;
> >>> +};
> >>> +// CHECK:      RecordDecl{{.*}}Test4
> >>> +// CHECK-NEXT:   DeprecatedAttr 0x{{[^ ]*}} <col:10> "" ""
> >>> +// CHECK-NEXT:   FieldDecl{{.*}}Test5
> >>> +// CHECK-NEXT:     DeprecatedAttr 0x{{[^ ]*}} <col:5, col:25>
> "Frobble"
> >>> ""
> >>> +// CHECK-NEXT:   FieldDecl{{.*}}Test6
> >>> +// CHECK-NEXT:     DeprecatedAttr 0x{{[^ ]*}} <col:5, col:25>
> "Frobble"
> >>> ""
> >>> +// CHECK-NEXT:   FieldDecl{{.*}}Test7
> >>> +// CHECK-NEXT:     IntegerLiteral{{.*}}'int' 12
> >>> +// CHECK-NEXT:     DeprecatedAttr 0x{{[^ ]*}} <col:15> "" ""
> >>> +
> >>> +struct [[deprecated]] Test8;
> >>> +// CHECK:      RecordDecl{{.*}}Test8
> >>> +// CHECK-NEXT:   DeprecatedAttr 0x{{[^ ]*}} <col:10> "" ""
> >>> +
> >>> +[[deprecated]] void Test9(int Test10 [[deprecated]]);
> >>> +// CHECK:      FunctionDecl{{.*}}Test9
> >>> +// CHECK-NEXT:   ParmVarDecl{{.*}}Test10
> >>> +// CHECK-NEXT:     DeprecatedAttr 0x{{[^ ]*}} <col:40> "" ""
> >>> +// CHECK-NEXT:   DeprecatedAttr 0x{{[^ ]*}} <col:3> "" ""
> >>> +
> >>> +void Test11 [[deprecated]](void);
> >>> +// CHECK:      FunctionDecl{{.*}}Test11
> >>> +// CHECK-NEXT:   DeprecatedAttr 0x{{[^ ]*}} <col:15> "" ""
> >>> +
> >>> +void Test12(void) [[deprecated]] {}
> >>> +// CHECK:      FunctionDecl{{.*}}Test12
> >>> +// CHECK-NEXT:   CompoundStmt
> >>> +// CHECK-NEXT:   DeprecatedAttr 0x{{[^ ]*}} <col:21> "" ""
> >>>
> >>> Added: cfe/trunk/test/Parser/c2x-attributes.c
> >>> URL:
> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/
> c2x-attributes.c?rev=315856&view=auto
> >>>
> >>> ============================================================
> ==================
> >>> --- cfe/trunk/test/Parser/c2x-attributes.c (added)
> >>> +++ cfe/trunk/test/Parser/c2x-attributes.c Sun Oct 15 08:01:42 2017
> >>> @@ -0,0 +1,122 @@
> >>> +// RUN: %clang_cc1 -fsyntax-only -fdouble-square-bracket-attributes
> >>> -verify %s
> >>> +
> >>> +enum [[]] E {
> >>> +  One [[]],
> >>> +  Two,
> >>> +  Three [[]]
> >>> +};
> >>> +
> >>> +enum [[]] { Four };
> >>> +[[]] enum E2 { Five }; // expected-error {{an attribute list cannot
> >>> appear here}}
> >>> +
> >>> +// FIXME: this diagnostic can be improved.
> >>> +enum { [[]] Six }; // expected-error {{expected identifier}}
> >>> +
> >>> +// FIXME: this diagnostic can be improved.
> >>> +enum E3 [[]] { Seven }; // expected-error {{expected identifier or
> '('}}
> >>> +
> >>> +struct [[]] S1 {
> >>> +  int i [[]];
> >>> +  int [[]] j;
> >>> +  int k[10] [[]];
> >>> +  int l[[]][10];
> >>> +  [[]] int m, n;
> >>> +  int o [[]] : 12;
> >>> +};
> >>> +
> >>> +[[]] struct S2 { int a; }; // expected-error {{an attribute list
> cannot
> >>> appear here}}
> >>> +struct S3 [[]] { int a; }; // expected-error {{an attribute list
> cannot
> >>> appear here}}
> >>> +
> >>> +union [[]] U {
> >>> +  double d [[]];
> >>> +  [[]] int i;
> >>> +};
> >>> +
> >>> +[[]] union U2 { double d; }; // expected-error {{an attribute list
> cannot
> >>> appear here}}
> >>> +union U3 [[]] { double d; }; // expected-error {{an attribute list
> cannot
> >>> appear here}}
> >>> +
> >>> +struct [[]] IncompleteStruct;
> >>> +union [[]] IncompleteUnion;
> >>> +enum [[]] IncompleteEnum;
> >>> +enum __attribute__((deprecated)) IncompleteEnum2;
> >>> +
> >>> +[[]] void f1(void);
> >>> +void [[]] f2(void);
> >>> +void f3 [[]] (void);
> >>> +void f4(void) [[]];
> >>> +
> >>> +void f5(int i [[]], [[]] int j, int [[]] k);
> >>> +
> >>> +void f6(a, b) [[]] int a; int b; { // expected-error {{an attribute
> list
> >>> cannot appear here}}
> >>> +}
> >>> +
> >>> +// FIXME: technically, an attribute list cannot appear here, but we
> >>> currently
> >>> +// parse it as part of the return type of the function, which is
> >>> reasonable
> >>> +// behavior given that we *don't* want to parse it as part of the K&R
> >>> parameter
> >>> +// declarations. It is disallowed to avoid a parsing ambiguity we
> already
> >>> +// handle well.
> >>> +int (*f7(a, b))(int, int) [[]] int a; int b; {
> >>> +  return 0;
> >>> +}
> >>> +
> >>> +[[]] int a, b;
> >>> +int c [[]], d [[]];
> >>> +
> >>> +void f8(void) [[]] {
> >>> +  [[]] int i, j;
> >>> +  int k, l [[]];
> >>> +}
> >>> +
> >>> +[[]] void f9(void) {
> >>> +  int i[10] [[]];
> >>> +  int (*fp1)(void)[[]];
> >>> +  int (*fp2 [[]])(void);
> >>> +
> >>> +  int * [[]] *ipp;
> >>> +}
> >>> +
> >>> +void f10(int j[static 10] [[]], int k[*] [[]]);
> >>> +
> >>> +void f11(void) {
> >>> +  [[]] {}
> >>> +  [[]] if (1) {}
> >>> +
> >>> +  [[]] switch (1) {
> >>> +  [[]] case 1: [[]] break;
> >>> +  [[]] default: break;
> >>> +  }
> >>> +
> >>> +  goto foo;
> >>> +  [[]] foo: (void)1;
> >>> +
> >>> +  [[]] for (;;);
> >>> +  [[]] while (1);
> >>> +  [[]] do [[]] { } while(1);
> >>> +
> >>> +  [[]] (void)1;
> >>> +
> >>> +  [[]];
> >>> +
> >>> +  (void)sizeof(int [4][[]]);
> >>> +  (void)sizeof(struct [[]] S3 { int a [[]]; });
> >>> +
> >>> +  [[]] return;
> >>> +}
> >>> +
> >>> +[[attr]] void f12(void); // expected-warning {{unknown attribute
> 'attr'
> >>> ignored}}
> >>> +[[vendor::attr]] void f13(void); // expected-warning {{unknown
> attribute
> >>> 'attr' ignored}}
> >>> +
> >>> +// Ensure that asm statements properly handle double colons.
> >>> +void test_asm(void) {
> >>> +  asm("ret" :::);
> >>> +  asm("foo" :: "r" (xx)); // expected-error {{use of undeclared
> >>> identifier 'xx'}}
> >>> +}
> >>> +
> >>> +// Do not allow 'using' to introduce vendor attribute namespaces.
> >>> +[[using vendor: attr1, attr2]] void f14(void); // expected-error
> >>> {{expected ']'}} \
> >>> +                                               // expected-warning
> >>> {{unknown attribute 'vendor' ignored}} \
> >>> +                                               // expected-warning
> >>> {{unknown attribute 'using' ignored}}
> >>> +
> >>> +struct [[]] S4 *s; // expected-error {{an attribute list cannot appear
> >>> here}}
> >>> +struct S5 {};
> >>> +int c = sizeof(struct [[]] S5); // expected-error {{an attribute list
> >>> cannot appear here}}
> >>>
> >>> Added: cfe/trunk/test/Parser/c2x-attributes.m
> >>> URL:
> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/
> c2x-attributes.m?rev=315856&view=auto
> >>>
> >>> ============================================================
> ==================
> >>> --- cfe/trunk/test/Parser/c2x-attributes.m (added)
> >>> +++ cfe/trunk/test/Parser/c2x-attributes.m Sun Oct 15 08:01:42 2017
> >>> @@ -0,0 +1,21 @@
> >>> +// RUN: %clang_cc1 -fsyntax-only -fdouble-square-bracket-attributes
> >>> -verify %s
> >>> +// expected-no-diagnostics
> >>> +
> >>> +enum __attribute__((deprecated)) E1 : int; // ok
> >>> +enum [[deprecated]] E2 : int;
> >>> +
> >>> + at interface Base
> >>> + at end
> >>> +
> >>> + at interface S : Base
> >>> +- (void) bar;
> >>> + at end
> >>> +
> >>> + at interface T : Base
> >>> +- (S *) foo;
> >>> + at end
> >>> +
> >>> +
> >>> +void f(T *t) {
> >>> +  [[]][[t foo] bar];
> >>> +}
> >>>
> >>> Added: cfe/trunk/test/Sema/attr-deprecated-c2x.c
> >>> URL:
> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/
> attr-deprecated-c2x.c?rev=315856&view=auto
> >>>
> >>> ============================================================
> ==================
> >>> --- cfe/trunk/test/Sema/attr-deprecated-c2x.c (added)
> >>> +++ cfe/trunk/test/Sema/attr-deprecated-c2x.c Sun Oct 15 08:01:42 2017
> >>> @@ -0,0 +1,54 @@
> >>> +// RUN: %clang_cc1 %s -verify -fsyntax-only
> >>> -fdouble-square-bracket-attributes
> >>> +
> >>> +int f() [[deprecated]]; // expected-note 2 {{'f' has been explicitly
> >>> marked deprecated here}}
> >>> +void g() [[deprecated]];// expected-note {{'g' has been explicitly
> marked
> >>> deprecated here}}
> >>> +void g();
> >>> +
> >>> +extern int var [[deprecated]]; // expected-note 2 {{'var' has been
> >>> explicitly marked deprecated here}}
> >>> +
> >>> +int a() {
> >>> +  int (*ptr)() = f; // expected-warning {{'f' is deprecated}}
> >>> +  f(); // expected-warning {{'f' is deprecated}}
> >>> +
> >>> +  // test if attributes propagate to functions
> >>> +  g(); // expected-warning {{'g' is deprecated}}
> >>> +
> >>> +  return var; // expected-warning {{'var' is deprecated}}
> >>> +}
> >>> +
> >>> +// test if attributes propagate to variables
> >>> +extern int var;
> >>> +int w() {
> >>> +  return var; // expected-warning {{'var' is deprecated}}
> >>> +}
> >>> +
> >>> +int old_fn() [[deprecated]];// expected-note {{'old_fn' has been
> >>> explicitly marked deprecated here}}
> >>> +int old_fn();
> >>> +int (*fn_ptr)() = old_fn; // expected-warning {{'old_fn' is
> deprecated}}
> >>> +
> >>> +int old_fn() {
> >>> +  return old_fn()+1;  // no warning, deprecated functions can use
> >>> deprecated symbols.
> >>> +}
> >>> +
> >>> +struct foo {
> >>> +  int x [[deprecated]]; // expected-note 3 {{'x' has been explicitly
> >>> marked deprecated here}}
> >>> +};
> >>> +
> >>> +void test1(struct foo *F) {
> >>> +  ++F->x;  // expected-warning {{'x' is deprecated}}
> >>> +  struct foo f1 = { .x = 17 }; // expected-warning {{'x' is
> deprecated}}
> >>> +  struct foo f2 = { 17 }; // expected-warning {{'x' is deprecated}}
> >>> +}
> >>> +
> >>> +typedef struct foo foo_dep [[deprecated]]; // expected-note
> {{'foo_dep'
> >>> has been explicitly marked deprecated here}}
> >>> +foo_dep *test2;    // expected-warning {{'foo_dep' is deprecated}}
> >>> +
> >>> +struct [[deprecated, // expected-note {{'bar_dep' has been explicitly
> >>> marked deprecated here}}
> >>> +         invalid_attribute]] bar_dep ;  // expected-warning {{unknown
> >>> attribute 'invalid_attribute' ignored}}
> >>> +
> >>> +struct bar_dep *test3;   // expected-warning {{'bar_dep' is
> deprecated}}
> >>> +
> >>> +[[deprecated("this is the message")]] int i; // expected-note {{'i'
> has
> >>> been explicitly marked deprecated here}}
> >>> +void test4(void) {
> >>> +  i = 12; // expected-warning {{'i' is deprecated: this is the
> message}}
> >>> +}
> >>>
> >>> Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
> >>> URL:
> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/
> TableGen/ClangAttrEmitter.cpp?rev=315856&r1=315855&r2=315856&view=diff
> >>>
> >>> ============================================================
> ==================
> >>> --- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
> >>> +++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Sun Oct 15 08:01:42
> 2017
> >>> @@ -58,7 +58,7 @@ public:
> >>>
> >>>      assert(V != "GCC" && "Given a GCC spelling, which means this
> hasn't
> >>> been"
> >>>             "flattened!");
> >>> -    if (V == "CXX11" || V == "Pragma")
> >>> +    if (V == "CXX11" || V == "C2x" || V == "Pragma")
> >>>        NS = Spelling.getValueAsString("Namespace");
> >>>      bool Unset;
> >>>      K = Spelling.getValueAsBitOrUnset("KnownToGCC", Unset);
> >>> @@ -1326,7 +1326,7 @@ writePrettyPrintFunction(Record &R,
> >>>      if (Variety == "GNU") {
> >>>        Prefix = " __attribute__((";
> >>>        Suffix = "))";
> >>> -    } else if (Variety == "CXX11") {
> >>> +    } else if (Variety == "CXX11" || Variety == "C2x") {
> >>>        Prefix = " [[";
> >>>        Suffix = "]]";
> >>>        std::string Namespace = Spellings[I].nameSpace();
> >>> @@ -2716,10 +2716,14 @@ static void GenerateHasAttrSpellingStrin
> >>>        // If this is the C++11 variety, also add in the LangOpts test.
> >>>        if (Variety == "CXX11")
> >>>          Test += " && LangOpts.CPlusPlus11";
> >>> +      else if (Variety == "C2x")
> >>> +        Test += " && LangOpts.DoubleSquareBracketAttributes";
> >>>      } else if (Variety == "CXX11")
> >>>        // C++11 mode should be checked against LangOpts, which is
> presumed
> >>> to be
> >>>        // present in the caller.
> >>>        Test = "LangOpts.CPlusPlus11";
> >>> +    else if (Variety == "C2x")
> >>> +      Test = "LangOpts.DoubleSquareBracketAttributes";
> >>>
> >>>      std::string TestStr =
> >>>          !Test.empty() ? Test + " ? " + llvm::itostr(Version) + " : 0"
> :
> >>> "1";
> >>> @@ -2740,7 +2744,7 @@ void EmitClangAttrHasAttrImpl(RecordKeep
> >>>    // and declspecs. Then generate a big switch statement for each of
> >>> them.
> >>>    std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("
> Attr");
> >>>    std::vector<Record *> Declspec, Microsoft, GNU, Pragma;
> >>> -  std::map<std::string, std::vector<Record *>> CXX;
> >>> +  std::map<std::string, std::vector<Record *>> CXX, C2x;
> >>>
> >>>    // Walk over the list of all attributes, and split them out based on
> >>> the
> >>>    // spelling variety.
> >>> @@ -2756,6 +2760,8 @@ void EmitClangAttrHasAttrImpl(RecordKeep
> >>>          Microsoft.push_back(R);
> >>>        else if (Variety == "CXX11")
> >>>          CXX[SI.nameSpace()].push_back(R);
> >>> +      else if (Variety == "C2x")
> >>> +        C2x[SI.nameSpace()].push_back(R);
> >>>        else if (Variety == "Pragma")
> >>>          Pragma.push_back(R);
> >>>      }
> >>> @@ -2775,20 +2781,25 @@ void EmitClangAttrHasAttrImpl(RecordKeep
> >>>    OS << "case AttrSyntax::Pragma:\n";
> >>>    OS << "  return llvm::StringSwitch<int>(Name)\n";
> >>>    GenerateHasAttrSpellingStringSwitch(Pragma, OS, "Pragma");
> >>> -  OS << "case AttrSyntax::CXX: {\n";
> >>> -  // C++11-style attributes are further split out based on the Scope.
> >>> -  for (auto I = CXX.cbegin(), E = CXX.cend(); I != E; ++I) {
> >>> -    if (I != CXX.begin())
> >>> -      OS << " else ";
> >>> -    if (I->first.empty())
> >>> -      OS << "if (!Scope || Scope->getName() == \"\") {\n";
> >>> -    else
> >>> -      OS << "if (Scope->getName() == \"" << I->first << "\") {\n";
> >>> -    OS << "  return llvm::StringSwitch<int>(Name)\n";
> >>> -    GenerateHasAttrSpellingStringSwitch(I->second, OS, "CXX11",
> >>> I->first);
> >>> -    OS << "}";
> >>> -  }
> >>> -  OS << "\n}\n";
> >>> +  auto fn = [&OS](const char *Spelling, const char *Variety,
> >>> +                  const std::map<std::string, std::vector<Record *>>
> >>> &List) {
> >>> +    OS << "case AttrSyntax::" << Variety << ": {\n";
> >>> +    // C++11-style attributes are further split out based on the
> Scope.
> >>> +    for (auto I = List.cbegin(), E = List.cend(); I != E; ++I) {
> >>> +      if (I != List.cbegin())
> >>> +        OS << " else ";
> >>> +      if (I->first.empty())
> >>> +        OS << "if (!Scope || Scope->getName() == \"\") {\n";
> >>> +      else
> >>> +        OS << "if (Scope->getName() == \"" << I->first << "\") {\n";
> >>> +      OS << "  return llvm::StringSwitch<int>(Name)\n";
> >>> +      GenerateHasAttrSpellingStringSwitch(I->second, OS, Spelling,
> >>> I->first);
> >>> +      OS << "}";
> >>> +    }
> >>> +    OS << "\n}\n";
> >>> +  };
> >>> +  fn("CXX11", "CXX", CXX);
> >>> +  fn("C2x", "C", C2x);
> >>>    OS << "}\n";
> >>>  }
> >>>
> >>> @@ -2809,10 +2820,11 @@ void EmitClangAttrSpellingListIndex(Reco
> >>>           << StringSwitch<unsigned>(Spellings[I].variety())
> >>>                  .Case("GNU", 0)
> >>>                  .Case("CXX11", 1)
> >>> -                .Case("Declspec", 2)
> >>> -                .Case("Microsoft", 3)
> >>> -                .Case("Keyword", 4)
> >>> -                .Case("Pragma", 5)
> >>> +                .Case("C2x", 2)
> >>> +                .Case("Declspec", 3)
> >>> +                .Case("Microsoft", 4)
> >>> +                .Case("Keyword", 5)
> >>> +                .Case("Pragma", 6)
> >>>                  .Default(0)
> >>>           << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
> >>>           << "        return " << I << ";\n";
> >>> @@ -3505,7 +3517,7 @@ void EmitClangAttrParsedAttrKinds(Record
> >>>
> >>>    std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("
> Attr");
> >>>    std::vector<StringMatcher::StringPair> GNU, Declspec, Microsoft,
> CXX11,
> >>> -      Keywords, Pragma;
> >>> +      Keywords, Pragma, C2x;
> >>>    std::set<std::string> Seen;
> >>>    for (const auto *A : Attrs) {
> >>>      const Record &Attr = *A;
> >>> @@ -3543,6 +3555,10 @@ void EmitClangAttrParsedAttrKinds(Record
> >>>            Matches = &CXX11;
> >>>            Spelling += S.nameSpace();
> >>>            Spelling += "::";
> >>> +        } else if (Variety == "C2x") {
> >>> +          Matches = &C2x;
> >>> +          Spelling += S.nameSpace();
> >>> +          Spelling += "::";
> >>>          } else if (Variety == "GNU")
> >>>            Matches = &GNU;
> >>>          else if (Variety == "Declspec")
> >>> @@ -3581,6 +3597,8 @@ void EmitClangAttrParsedAttrKinds(Record
> >>>    StringMatcher("Name", Microsoft, OS).Emit();
> >>>    OS << "  } else if (AttributeList::AS_CXX11 == Syntax) {\n";
> >>>    StringMatcher("Name", CXX11, OS).Emit();
> >>> +  OS << "  } else if (AttributeList::AS_C2x == Syntax) {\n";
> >>> +  StringMatcher("Name", C2x, OS).Emit();
> >>>    OS << "  } else if (AttributeList::AS_Keyword == Syntax || ";
> >>>    OS << "AttributeList::AS_ContextSensitiveKeyword == Syntax) {\n";
> >>>    StringMatcher("Name", Keywords, OS).Emit();
> >>> @@ -3666,10 +3684,11 @@ static void WriteCategoryHeader(const Re
> >>>  enum SpellingKind {
> >>>    GNU = 1 << 0,
> >>>    CXX11 = 1 << 1,
> >>> -  Declspec = 1 << 2,
> >>> -  Microsoft = 1 << 3,
> >>> -  Keyword = 1 << 4,
> >>> -  Pragma = 1 << 5
> >>> +  C2x = 1 << 2,
> >>> +  Declspec = 1 << 3,
> >>> +  Microsoft = 1 << 4,
> >>> +  Keyword = 1 << 5,
> >>> +  Pragma = 1 << 6
> >>>  };
> >>>
> >>>  static void WriteDocumentation(RecordKeeper &Records,
> >>> @@ -3716,6 +3735,7 @@ static void WriteDocumentation(RecordKee
> >>>      SpellingKind Kind = StringSwitch<SpellingKind>(I.variety())
> >>>                              .Case("GNU", GNU)
> >>>                              .Case("CXX11", CXX11)
> >>> +                            .Case("C2x", C2x)
> >>>                              .Case("Declspec", Declspec)
> >>>                              .Case("Microsoft", Microsoft)
> >>>                              .Case("Keyword", Keyword)
> >>> @@ -3725,7 +3745,7 @@ static void WriteDocumentation(RecordKee
> >>>      SupportedSpellings |= Kind;
> >>>
> >>>      std::string Name;
> >>> -    if (Kind == CXX11 && !I.nameSpace().empty())
> >>> +    if ((Kind == CXX11 || Kind == C2x) && !I.nameSpace().empty())
> >>>        Name = I.nameSpace() + "::";
> >>>      Name += I.name();
> >>>
> >>> @@ -3754,13 +3774,15 @@ static void WriteDocumentation(RecordKee
> >>>
> >>>    // List what spelling syntaxes the attribute supports.
> >>>    OS << ".. csv-table:: Supported Syntaxes\n";
> >>> -  OS << "   :header: \"GNU\", \"C++11\", \"__declspec\",
> \"Keyword\",";
> >>> +  OS << "   :header: \"GNU\", \"C++11\", \"C2x\", \"__declspec\",
> >>> \"Keyword\",";
> >>>    OS << " \"Pragma\", \"Pragma clang attribute\"\n\n";
> >>>    OS << "   \"";
> >>>    if (SupportedSpellings & GNU) OS << "X";
> >>>    OS << "\",\"";
> >>>    if (SupportedSpellings & CXX11) OS << "X";
> >>>    OS << "\",\"";
> >>> +  if (SupportedSpellings & C2x) OS << "X";
> >>> +  OS << "\",\"";
> >>>    if (SupportedSpellings & Declspec) OS << "X";
> >>>    OS << "\",\"";
> >>>    if (SupportedSpellings & Keyword) OS << "X";
> >>>
> >>>
> >>> _______________________________________________
> >>> cfe-commits mailing list
> >>> cfe-commits at lists.llvm.org
> >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
> >>
> >>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20171018/38ad0606/attachment-0001.html>


More information about the cfe-commits mailing list