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.
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 18 07:38:13 PDT 2017
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
>>
>>
More information about the cfe-commits
mailing list