summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp6
-rw-r--r--clang/lib/Lex/Lexer.cpp4
-rw-r--r--clang/lib/Parse/ParseDecl.cpp34
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp35
-rw-r--r--clang/lib/Sema/AttributeList.cpp5
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;
OpenPOWER on IntegriCloud