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.
Saleem Abdulrasool via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 15 09:52:38 PDT 2017
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.
>
Since this is a new option and one that GCC doesn't have ... it seems
pretty cumbersome to write. Would you be open to renaming this? Perhaps
something like `-fgeneralized-attributes` which IIRC was the name for the
C++11 specification.
> 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
>
--
Saleem Abdulrasool
compnerd (at) compnerd (dot) org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20171015/c96bd475/attachment-0001.html>
More information about the cfe-commits
mailing list