diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Lex/Lexer.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 34 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 35 | ||||
-rw-r--r-- | clang/lib/Sema/AttributeList.cpp | 5 |
5 files changed, 56 insertions, 28 deletions
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 7114e654dab..9a4fc774f47 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2138,6 +2138,12 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, && 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); diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index b85e0f03dc0..5132d0e62c2 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -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 { diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 21cdc62a186..cc032c8cf3f 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1562,7 +1562,7 @@ void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) { 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(DeclSpec &DS, 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(DeclSpec &DS, /// 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(SourceLocation StartLoc, Decl *EnumDecl) { 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(Declarator &D, 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(Declarator &D, 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(Declarator &D, TrailingReturnType = ParseTrailingReturnType(Range); EndLoc = Range.getEnd(); } + } else if (standardAttributesAllowed()) { + MaybeParseCXX11Attributes(FnAttrs); } } diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 25bb053afc2..ada67e84d21 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -3814,7 +3814,7 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) { } 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(IdentifierInfo *AttrName, 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(IdentifierInfo *AttrName, // 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(IdentifierInfo *AttrName, 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(IdentifierInfo *AttrName, 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::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, 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::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, 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::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, 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) diff --git a/clang/lib/Sema/AttributeList.cpp b/clang/lib/Sema/AttributeList.cpp index 724db456785..14d334746f1 100644 --- a/clang/lib/Sema/AttributeList.cpp +++ b/clang/lib/Sema/AttributeList.cpp @@ -114,7 +114,8 @@ static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName, // 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::getKind(const IdentifierInfo *Name, // 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; |