summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Parse
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse')
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp63
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp361
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp429
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp145
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp74
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp180
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp18
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp59
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp70
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp45
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp71
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/Parser.cpp74
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h22
15 files changed, 1122 insertions, 507 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
index 59b491a..ea67a52 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -26,12 +26,10 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
AttributeList *AccessAttrs,
ParsingDeclarator &D,
const ParsedTemplateInfo &TemplateInfo,
- const VirtSpecifiers& VS,
- FunctionDefinitionKind DefinitionKind,
+ const VirtSpecifiers& VS,
ExprResult& Init) {
assert(D.isFunctionDeclarator() && "This isn't a function declarator!");
- assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try) ||
- Tok.is(tok::equal)) &&
+ assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try, tok::equal) &&
"Current token not a '{', ':', '=', or 'try'!");
MultiTemplateParamsArg TemplateParams(
@@ -40,7 +38,6 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0);
NamedDecl *FnD;
- D.setFunctionDefinitionKind(DefinitionKind);
if (D.getDeclSpec().isFriendSpecified())
FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D,
TemplateParams);
@@ -71,17 +68,24 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
bool Delete = false;
SourceLocation KWLoc;
+ SourceLocation KWEndLoc = Tok.getEndLoc().getLocWithOffset(-1);
if (TryConsumeToken(tok::kw_delete, KWLoc)) {
Diag(KWLoc, getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_deleted_function
: diag::ext_deleted_function);
Actions.SetDeclDeleted(FnD, KWLoc);
Delete = true;
+ if (auto *DeclAsFunction = dyn_cast<FunctionDecl>(FnD)) {
+ DeclAsFunction->setRangeEnd(KWEndLoc);
+ }
} else if (TryConsumeToken(tok::kw_default, KWLoc)) {
Diag(KWLoc, getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_defaulted_function
: diag::ext_defaulted_function);
Actions.SetDeclDefaulted(FnD, KWLoc);
+ if (auto *DeclAsFunction = dyn_cast<FunctionDecl>(FnD)) {
+ DeclAsFunction->setRangeEnd(KWEndLoc);
+ }
} else {
llvm_unreachable("function definition after = not 'delete' or 'default'");
}
@@ -97,12 +101,12 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
return FnD;
}
-
+
// In delayed template parsing mode, if we are within a class template
// or if we are about to parse function member template then consume
// the tokens and store them for parsing at the end of the translation unit.
if (getLangOpts().DelayedTemplateParsing &&
- DefinitionKind == FDK_Definition &&
+ D.getFunctionDefinitionKind() == FDK_Definition &&
!D.getDeclSpec().isConstexprSpecified() &&
!(FnD && FnD->getAsFunction() &&
FnD->getAsFunction()->getReturnType()->getContainedAutoType()) &&
@@ -186,7 +190,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
/// declaration. Now lex its initializer and store its tokens for parsing
/// after the class is complete.
void Parser::ParseCXXNonStaticMemberInitializer(Decl *VarD) {
- assert((Tok.is(tok::l_brace) || Tok.is(tok::equal)) &&
+ assert(Tok.isOneOf(tok::l_brace, tok::equal) &&
"Current token not a '{' or '='!");
LateParsedMemberInitializer *MI =
@@ -306,9 +310,10 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope |
Scope::FunctionDeclarationScope | Scope::DeclScope);
for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {
+ auto Param = cast<ParmVarDecl>(LM.DefaultArgs[I].Param);
// Introduce the parameter into scope.
- Actions.ActOnDelayedCXXMethodParameter(getCurScope(),
- LM.DefaultArgs[I].Param);
+ bool HasUnparsed = Param->hasUnparsedDefaultArg();
+ Actions.ActOnDelayedCXXMethodParameter(getCurScope(), Param);
if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) {
// Mark the end of the default argument so that we know when to stop when
// we parse it later on.
@@ -316,9 +321,8 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
Token DefArgEnd;
DefArgEnd.startToken();
DefArgEnd.setKind(tok::eof);
- DefArgEnd.setLocation(LastDefaultArgToken.getLocation().getLocWithOffset(
- LastDefaultArgToken.getLength()));
- DefArgEnd.setEofData(LM.DefaultArgs[I].Param);
+ DefArgEnd.setLocation(LastDefaultArgToken.getEndLoc());
+ DefArgEnd.setEofData(Param);
Toks->push_back(DefArgEnd);
// Parse the default argument from its saved token stream.
@@ -336,7 +340,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
// used.
EnterExpressionEvaluationContext Eval(Actions,
Sema::PotentiallyEvaluatedIfUsed,
- LM.DefaultArgs[I].Param);
+ Param);
ExprResult DefArgResult;
if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
@@ -346,11 +350,9 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
DefArgResult = ParseAssignmentExpression();
DefArgResult = Actions.CorrectDelayedTyposInExpr(DefArgResult);
if (DefArgResult.isInvalid()) {
- Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param,
- EqualLoc);
+ Actions.ActOnParamDefaultArgumentError(Param, EqualLoc);
} else {
- if (Tok.isNot(tok::eof) ||
- Tok.getEofData() != LM.DefaultArgs[I].Param) {
+ if (Tok.isNot(tok::eof) || Tok.getEofData() != Param) {
// The last two tokens are the terminator and the saved value of
// Tok; the last token in the default argument is the one before
// those.
@@ -359,7 +361,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
<< SourceRange(Tok.getLocation(),
(*Toks)[Toks->size() - 3].getLocation());
}
- Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc,
+ Actions.ActOnParamDefaultArgument(Param, EqualLoc,
DefArgResult.get());
}
@@ -368,11 +370,21 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
while (Tok.isNot(tok::eof))
ConsumeAnyToken();
- if (Tok.is(tok::eof) && Tok.getEofData() == LM.DefaultArgs[I].Param)
+ if (Tok.is(tok::eof) && Tok.getEofData() == Param)
ConsumeAnyToken();
delete Toks;
LM.DefaultArgs[I].Toks = nullptr;
+ } else if (HasUnparsed) {
+ assert(Param->hasInheritedDefaultArg());
+ FunctionDecl *Old = cast<FunctionDecl>(LM.Method)->getPreviousDecl();
+ ParmVarDecl *OldParam = Old->getParamDecl(I);
+ assert (!OldParam->hasUnparsedDefaultArg());
+ if (OldParam->hasUninstantiatedDefaultArg())
+ Param->setUninstantiatedDefaultArg(
+ Param->getUninstantiatedDefaultArg());
+ else
+ Param->setDefaultArg(OldParam->getInit());
}
}
@@ -383,9 +395,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
Token ExceptionSpecEnd;
ExceptionSpecEnd.startToken();
ExceptionSpecEnd.setKind(tok::eof);
- ExceptionSpecEnd.setLocation(
- LastExceptionSpecToken.getLocation().getLocWithOffset(
- LastExceptionSpecToken.getLength()));
+ ExceptionSpecEnd.setLocation(LastExceptionSpecToken.getEndLoc());
ExceptionSpecEnd.setEofData(LM.Method);
Toks->push_back(ExceptionSpecEnd);
@@ -490,8 +500,7 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
Token BodyEnd;
BodyEnd.startToken();
BodyEnd.setKind(tok::eof);
- BodyEnd.setLocation(
- LastBodyToken.getLocation().getLocWithOffset(LastBodyToken.getLength()));
+ BodyEnd.setLocation(LastBodyToken.getEndLoc());
BodyEnd.setEofData(LM.D);
LM.Toks.push_back(BodyEnd);
// Append the current token at the end of the new token stream so that it
@@ -501,7 +510,7 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
// Consume the previously pushed token.
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
- assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
+ assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try)
&& "Inline method not starting with '{', ':' or 'try'");
// Parse the method body. Function body parsing code is similar enough
@@ -816,7 +825,7 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
}
}
- if (Tok.is(tok::identifier) || Tok.is(tok::kw_template)) {
+ if (Tok.isOneOf(tok::identifier, tok::kw_template)) {
Toks.push_back(Tok);
ConsumeToken();
} else if (Tok.is(tok::code_completion)) {
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
index 4d05e16..1c52552 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
@@ -285,7 +285,7 @@ unsigned Parser::ParseAttributeArgsCommon(
if (AttrKind == AttributeList::UnknownAttribute ||
AttrKind == AttributeList::IgnoredAttribute) {
const Token &Next = NextToken();
- IsIdentifierArg = Next.is(tok::r_paren) || Next.is(tok::comma);
+ IsIdentifierArg = Next.isOneOf(tok::r_paren, tok::comma);
}
if (IsIdentifierArg)
@@ -529,64 +529,72 @@ bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,
/// [MS] extended-decl-modifier-seq:
/// extended-decl-modifier[opt]
/// extended-decl-modifier extended-decl-modifier-seq
-void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &Attrs) {
+void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs,
+ SourceLocation *End) {
+ assert((getLangOpts().MicrosoftExt || getLangOpts().Borland ||
+ getLangOpts().CUDA) &&
+ "Incorrect language options for parsing __declspec");
assert(Tok.is(tok::kw___declspec) && "Not a declspec!");
- ConsumeToken();
- BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen_after, "__declspec",
- tok::r_paren))
- return;
-
- // An empty declspec is perfectly legal and should not warn. Additionally,
- // you can specify multiple attributes per declspec.
- while (Tok.isNot(tok::r_paren)) {
- // Attribute not present.
- if (TryConsumeToken(tok::comma))
- continue;
-
- // We expect either a well-known identifier or a generic string. Anything
- // else is a malformed declspec.
- bool IsString = Tok.getKind() == tok::string_literal ? true : false;
- if (!IsString && Tok.getKind() != tok::identifier &&
- Tok.getKind() != tok::kw_restrict) {
- Diag(Tok, diag::err_ms_declspec_type);
- T.skipToEnd();
+ while (Tok.is(tok::kw___declspec)) {
+ ConsumeToken();
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ if (T.expectAndConsume(diag::err_expected_lparen_after, "__declspec",
+ tok::r_paren))
return;
- }
- IdentifierInfo *AttrName;
- SourceLocation AttrNameLoc;
- if (IsString) {
- SmallString<8> StrBuffer;
- bool Invalid = false;
- StringRef Str = PP.getSpelling(Tok, StrBuffer, &Invalid);
- if (Invalid) {
+ // An empty declspec is perfectly legal and should not warn. Additionally,
+ // you can specify multiple attributes per declspec.
+ while (Tok.isNot(tok::r_paren)) {
+ // Attribute not present.
+ if (TryConsumeToken(tok::comma))
+ continue;
+
+ // We expect either a well-known identifier or a generic string. Anything
+ // else is a malformed declspec.
+ bool IsString = Tok.getKind() == tok::string_literal;
+ if (!IsString && Tok.getKind() != tok::identifier &&
+ Tok.getKind() != tok::kw_restrict) {
+ Diag(Tok, diag::err_ms_declspec_type);
T.skipToEnd();
return;
}
- AttrName = PP.getIdentifierInfo(Str);
- AttrNameLoc = ConsumeStringToken();
- } else {
- AttrName = Tok.getIdentifierInfo();
- AttrNameLoc = ConsumeToken();
- }
- bool AttrHandled = false;
+ IdentifierInfo *AttrName;
+ SourceLocation AttrNameLoc;
+ if (IsString) {
+ SmallString<8> StrBuffer;
+ bool Invalid = false;
+ StringRef Str = PP.getSpelling(Tok, StrBuffer, &Invalid);
+ if (Invalid) {
+ T.skipToEnd();
+ return;
+ }
+ AttrName = PP.getIdentifierInfo(Str);
+ AttrNameLoc = ConsumeStringToken();
+ } else {
+ AttrName = Tok.getIdentifierInfo();
+ AttrNameLoc = ConsumeToken();
+ }
+
+ bool AttrHandled = false;
- // Parse attribute arguments.
- if (Tok.is(tok::l_paren))
- AttrHandled = ParseMicrosoftDeclSpecArgs(AttrName, AttrNameLoc, Attrs);
- else if (AttrName->getName() == "property")
- // The property attribute must have an argument list.
- Diag(Tok.getLocation(), diag::err_expected_lparen_after)
- << AttrName->getName();
+ // Parse attribute arguments.
+ if (Tok.is(tok::l_paren))
+ AttrHandled = ParseMicrosoftDeclSpecArgs(AttrName, AttrNameLoc, Attrs);
+ else if (AttrName->getName() == "property")
+ // The property attribute must have an argument list.
+ Diag(Tok.getLocation(), diag::err_expected_lparen_after)
+ << AttrName->getName();
- if (!AttrHandled)
- Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
- AttributeList::AS_Declspec);
+ if (!AttrHandled)
+ Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
+ AttributeList::AS_Declspec);
+ }
+ T.consumeClose();
+ if (End)
+ *End = T.getCloseLocation();
}
- T.consumeClose();
}
void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) {
@@ -679,6 +687,28 @@ void Parser::ParseOpenCLQualifiers(ParsedAttributes &Attrs) {
AttributeList::AS_Keyword);
}
+void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) {
+ // Treat these like attributes, even though they're type specifiers.
+ while (true) {
+ switch (Tok.getKind()) {
+ case tok::kw___nonnull:
+ case tok::kw___nullable:
+ case tok::kw___null_unspecified: {
+ IdentifierInfo *AttrName = Tok.getIdentifierInfo();
+ SourceLocation AttrNameLoc = ConsumeToken();
+ if (!getLangOpts().ObjC1)
+ Diag(AttrNameLoc, diag::ext_nullability)
+ << AttrName;
+ attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
+ AttributeList::AS_Keyword);
+ break;
+ }
+ default:
+ return;
+ }
+ }
+}
+
static bool VersionNumberSeparator(const char Separator) {
return (Separator == '.' || Separator == '_');
}
@@ -1360,6 +1390,46 @@ void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs) {
}
}
+// As an exception to the rule, __declspec(align(...)) before the
+// class-key affects the type instead of the variable.
+void Parser::handleDeclspecAlignBeforeClassKey(ParsedAttributesWithRange &Attrs,
+ DeclSpec &DS,
+ Sema::TagUseKind TUK) {
+ if (TUK == Sema::TUK_Reference)
+ return;
+
+ ParsedAttributes &PA = DS.getAttributes();
+ AttributeList *AL = PA.getList();
+ AttributeList *Prev = nullptr;
+ while (AL) {
+ AttributeList *Next = AL->getNext();
+
+ // We only consider attributes using the appropriate '__declspec' spelling,
+ // this behavior doesn't extend to any other spellings.
+ if (AL->getKind() == AttributeList::AT_Aligned &&
+ AL->isDeclspecAttribute()) {
+ // Stitch the attribute into the tag's attribute list.
+ AL->setNext(nullptr);
+ Attrs.add(AL);
+
+ // Remove the attribute from the variable's attribute list.
+ if (Prev) {
+ // Set the last variable attribute's next attribute to be the attribute
+ // after the current one.
+ Prev->setNext(Next);
+ } else {
+ // Removing the head of the list requires us to reset the head to the
+ // next attribute.
+ PA.set(Next);
+ }
+ } else {
+ Prev = AL;
+ }
+
+ AL = Next;
+ }
+}
+
/// ParseDeclaration - Parse a full 'declaration', which consists of
/// declaration-specifiers, some number of declarators, and a semicolon.
/// 'Context' should be a Declarator::TheContext value. This returns the
@@ -1551,7 +1621,7 @@ void Parser::SkipMalformedDecl() {
// a malformed class or function definition or similar.
ConsumeBrace();
SkipUntil(tok::r_brace);
- if (Tok.is(tok::comma) || Tok.is(tok::l_brace) || Tok.is(tok::kw_try)) {
+ if (Tok.isOneOf(tok::comma, tok::l_brace, tok::kw_try)) {
// This declaration isn't over yet. Keep skipping.
continue;
}
@@ -1657,7 +1727,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
// and we don't have any other declarators in this declaration.
bool Fixit = !DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID);
MaybeParseGNUAttributes(D, &LateParsedAttrs);
- Fixit &= Tok.is(tok::semi) || Tok.is(tok::l_brace) || Tok.is(tok::kw_try);
+ Fixit &= Tok.isOneOf(tok::semi, tok::l_brace, tok::kw_try);
Diag(Loc, diag::err_c11_noreturn_misplaced)
<< (Fixit ? FixItHint::CreateRemoval(Loc) : FixItHint())
@@ -1691,11 +1761,12 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
}
if (isDeclarationSpecifier()) {
- // If there is an invalid declaration specifier right after the function
- // prototype, then we must be in a missing semicolon case where this isn't
- // actually a body. Just fall through into the code that handles it as a
- // prototype, and let the top-level code handle the erroneous declspec
- // where it would otherwise expect a comma or semicolon.
+ // If there is an invalid declaration specifier right after the
+ // function prototype, then we must be in a missing semicolon case
+ // where this isn't actually a body. Just fall through into the code
+ // that handles it as a prototype, and let the top-level code handle
+ // the erroneous declspec where it would otherwise expect a comma or
+ // semicolon.
} else {
Diag(Tok, diag::err_expected_fn_body);
SkipUntil(tok::semi);
@@ -1993,7 +2064,11 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl);
}
- if (ParseExpressionList(Exprs, CommaLocs)) {
+ if (ParseExpressionList(Exprs, CommaLocs, [&] {
+ Actions.CodeCompleteConstructor(getCurScope(),
+ cast<VarDecl>(ThisDecl)->getType()->getCanonicalTypeInternal(),
+ ThisDecl->getLocation(), Exprs);
+ })) {
Actions.ActOnInitializerError(ThisDecl);
SkipUntil(tok::r_paren, StopAtSemi);
@@ -2123,9 +2198,9 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS,
/// int (x)
///
static bool isValidAfterIdentifierInDeclarator(const Token &T) {
- return T.is(tok::l_square) || T.is(tok::l_paren) || T.is(tok::r_paren) ||
- T.is(tok::semi) || T.is(tok::comma) || T.is(tok::equal) ||
- T.is(tok::kw_asm) || T.is(tok::l_brace) || T.is(tok::colon);
+ return T.isOneOf(tok::l_square, tok::l_paren, tok::r_paren, tok::semi,
+ tok::comma, tok::equal, tok::kw_asm, tok::l_brace,
+ tok::colon);
}
@@ -2385,7 +2460,7 @@ ExprResult Parser::ParseAlignArgument(SourceLocation Start,
/// [C++11] 'alignas' '(' assignment-expression ...[opt] ')'
void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
SourceLocation *EndLoc) {
- assert((Tok.is(tok::kw_alignas) || Tok.is(tok::kw__Alignas)) &&
+ assert(Tok.isOneOf(tok::kw_alignas, tok::kw__Alignas) &&
"Not an alignment-specifier!");
IdentifierInfo *KWName = Tok.getIdentifierInfo();
@@ -2428,8 +2503,8 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level);
if (getLangOpts().CPlusPlus &&
- (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
- Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id)) &&
+ Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype,
+ tok::annot_template_id) &&
TryAnnotateCXXScopeToken(EnteringContext)) {
SkipMalformedDecl();
return true;
@@ -2442,7 +2517,7 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
// Determine whether the following tokens could possibly be a
// declarator.
bool MightBeDeclarator = true;
- if (Tok.is(tok::kw_typename) || Tok.is(tok::annot_typename)) {
+ if (Tok.isOneOf(tok::kw_typename, tok::annot_typename)) {
// A declarator-id can't start with 'typename'.
MightBeDeclarator = false;
} else if (AfterScope.is(tok::annot_template_id)) {
@@ -2457,9 +2532,8 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
// These tokens cannot come after the declarator-id in a
// simple-declaration, and are likely to come after a type-specifier.
- if (Next.is(tok::star) || Next.is(tok::amp) || Next.is(tok::ampamp) ||
- Next.is(tok::identifier) || Next.is(tok::annot_cxxscope) ||
- Next.is(tok::coloncolon)) {
+ if (Next.isOneOf(tok::star, tok::amp, tok::ampamp, tok::identifier,
+ tok::annot_cxxscope, tok::coloncolon)) {
// Missing a semicolon.
MightBeDeclarator = false;
} else if (HasScope) {
@@ -2564,7 +2638,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level);
bool AttrsLastTime = false;
ParsedAttributesWithRange attrs(AttrFactory);
- const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
+ // We use Sema's policy to get bool macros right.
+ const PrintingPolicy &Policy = Actions.getPrintingPolicy();
while (1) {
bool isInvalid = false;
bool isStorageClass = false;
@@ -2866,14 +2941,27 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if (DS.isTypeAltiVecVector())
goto DoneWithDeclSpec;
+ if (DSContext == DSC_objc_method_result && isObjCInstancetype()) {
+ ParsedType TypeRep = Actions.ActOnObjCInstanceType(Loc);
+ assert(TypeRep);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
+ DiagID, TypeRep, Policy);
+ if (isInvalid)
+ break;
+
+ DS.SetRangeEnd(Loc);
+ ConsumeToken();
+ continue;
+ }
+
ParsedType TypeRep =
Actions.getTypeName(*Tok.getIdentifierInfo(),
Tok.getLocation(), getCurScope());
// MSVC: If we weren't able to parse a default template argument, and it's
- // just a simple identifier, create a DependentNameType. This will allow us
- // to defer the name lookup to template instantiation time, as long we forge a
- // NestedNameSpecifier for the current context.
+ // just a simple identifier, create a DependentNameType. This will allow
+ // us to defer the name lookup to template instantiation time, as long we
+ // forge a NestedNameSpecifier for the current context.
if (!TypeRep && DSContext == DSC_template_type_arg &&
getLangOpts().MSVCCompat && getCurScope()->isTemplateParamScope()) {
TypeRep = Actions.ActOnDelayedDefaultTemplateArg(
@@ -2950,7 +3038,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// Microsoft declspec support.
case tok::kw___declspec:
- ParseMicrosoftDeclSpec(DS.getAttributes());
+ ParseMicrosoftDeclSpecs(DS.getAttributes());
continue;
// Microsoft single token adornments.
@@ -2987,6 +3075,13 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
ParseOpenCLAttributes(DS.getAttributes());
continue;
+ // Nullability type specifiers.
+ case tok::kw___nonnull:
+ case tok::kw___nullable:
+ case tok::kw___null_unspecified:
+ ParseNullabilityTypeSpecifiers(DS.getAttributes());
+ continue;
+
// storage-class-specifier
case tok::kw_typedef:
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_typedef, Loc,
@@ -3594,16 +3689,13 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseGNUAttributes(attrs);
MaybeParseCXX11Attributes(attrs);
-
- // If declspecs exist after tag, parse them.
- while (Tok.is(tok::kw___declspec))
- ParseMicrosoftDeclSpec(attrs);
+ MaybeParseMicrosoftDeclSpecs(attrs);
SourceLocation ScopedEnumKWLoc;
bool IsScopedUsingClassTag = false;
// In C++11, recognize 'enum class' and 'enum struct'.
- if (Tok.is(tok::kw_class) || Tok.is(tok::kw_struct)) {
+ if (Tok.isOneOf(tok::kw_class, tok::kw_struct)) {
Diag(Tok, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_scoped_enum
: diag::ext_scoped_enum);
IsScopedUsingClassTag = Tok.is(tok::kw_class);
@@ -3616,8 +3708,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
// They are allowed afterwards, though.
MaybeParseGNUAttributes(attrs);
MaybeParseCXX11Attributes(attrs);
- while (Tok.is(tok::kw___declspec))
- ParseMicrosoftDeclSpec(attrs);
+ MaybeParseMicrosoftDeclSpecs(attrs);
}
// C++11 [temp.explicit]p12:
@@ -3644,11 +3735,12 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
// if a fixed underlying type is allowed.
ColonProtectionRAIIObject X(*this, AllowFixedUnderlyingType);
- if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(),
+ CXXScopeSpec Spec;
+ if (ParseOptionalCXXScopeSpecifier(Spec, ParsedType(),
/*EnteringContext=*/true))
return;
- if (SS.isSet() && Tok.isNot(tok::identifier)) {
+ if (Spec.isSet() && Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected) << tok::identifier;
if (Tok.isNot(tok::l_brace)) {
// Has no name and is not a definition.
@@ -3657,6 +3749,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
return;
}
}
+
+ SS = Spec;
}
// Must have either 'enum name' or 'enum {...}'.
@@ -3842,6 +3936,15 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
return;
}
+ handleDeclspecAlignBeforeClassKey(attrs, DS, TUK);
+
+ Sema::SkipBodyInfo SkipBody;
+ if (!Name && TUK == Sema::TUK_Definition && Tok.is(tok::l_brace) &&
+ NextToken().is(tok::identifier))
+ SkipBody = Actions.shouldSkipAnonEnumBody(getCurScope(),
+ NextToken().getIdentifierInfo(),
+ NextToken().getLocation());
+
bool Owned = false;
bool IsDependent = false;
const char *PrevSpec = nullptr;
@@ -3851,7 +3954,22 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
AS, DS.getModulePrivateSpecLoc(), TParams,
Owned, IsDependent, ScopedEnumKWLoc,
IsScopedUsingClassTag, BaseType,
- DSC == DSC_type_specifier);
+ DSC == DSC_type_specifier, &SkipBody);
+
+ if (SkipBody.ShouldSkip) {
+ assert(TUK == Sema::TUK_Definition && "can only skip a definition");
+
+ BalancedDelimiterTracker T(*this, tok::l_brace);
+ T.consumeOpen();
+ T.skipToEnd();
+
+ if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,
+ NameLoc.isValid() ? NameLoc : StartLoc,
+ PrevSpec, DiagID, TagDecl, Owned,
+ Actions.getASTContext().getPrintingPolicy()))
+ Diag(StartLoc, DiagID) << PrevSpec;
+ return;
+ }
if (IsDependent) {
// This enum has a dependent nested-name-specifier. Handle it as a
@@ -3923,6 +4041,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
Diag(Tok, diag::error_empty_enum);
SmallVector<Decl *, 32> EnumConstantDecls;
+ SmallVector<SuppressAccessChecks, 32> EnumAvailabilityDiags;
Decl *LastEnumConstDecl = nullptr;
@@ -3953,7 +4072,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
SourceLocation EqualLoc;
ExprResult AssignedVal;
- ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
+ EnumAvailabilityDiags.emplace_back(*this);
if (TryConsumeToken(tok::equal, EqualLoc)) {
AssignedVal = ParseConstantExpression();
@@ -3967,7 +4086,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
IdentLoc, Ident,
attrs.getList(), EqualLoc,
AssignedVal.get());
- PD.complete(EnumConstDecl);
+ EnumAvailabilityDiags.back().done();
EnumConstantDecls.push_back(EnumConstDecl);
LastEnumConstDecl = EnumConstDecl;
@@ -4023,6 +4142,14 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
getCurScope(),
attrs.getList());
+ // Now handle enum constant availability diagnostics.
+ assert(EnumConstantDecls.size() == EnumAvailabilityDiags.size());
+ for (size_t i = 0, e = EnumConstantDecls.size(); i != e; ++i) {
+ ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
+ EnumAvailabilityDiags[i].redelay();
+ PD.complete(EnumConstantDecls[i]);
+ }
+
EnumScope.Exit();
Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl,
T.getCloseLocation());
@@ -4199,6 +4326,10 @@ bool Parser::isTypeSpecifierQualifier() {
case tok::kw___pascal:
case tok::kw___unaligned:
+ case tok::kw___nonnull:
+ case tok::kw___nullable:
+ case tok::kw___null_unspecified:
+
case tok::kw___private:
case tok::kw___local:
case tok::kw___global:
@@ -4372,6 +4503,10 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::kw___pascal:
case tok::kw___unaligned:
+ case tok::kw___nonnull:
+ case tok::kw___nullable:
+ case tok::kw___null_unspecified:
+
case tok::kw___private:
case tok::kw___local:
case tok::kw___global:
@@ -4397,7 +4532,7 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified) {
}
// Parse the constructor name.
- if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) {
+ if (Tok.isOneOf(tok::identifier, tok::annot_template_id)) {
// We already know that we have a constructor name; just consume
// the token.
ConsumeToken();
@@ -4601,6 +4736,14 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs,
continue;
}
goto DoneWithTypeQuals;
+
+ // Nullability type specifiers.
+ case tok::kw___nonnull:
+ case tok::kw___nullable:
+ case tok::kw___null_unspecified:
+ ParseNullabilityTypeSpecifiers(DS.getAttributes());
+ continue;
+
case tok::kw___attribute:
if (AttrReqs & AR_GNUAttributesParsedAndRejected)
// When GNU attributes are expressly forbidden, diagnose their usage.
@@ -4773,7 +4916,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc,
DS.getConstSpecLoc(),
DS.getVolatileSpecLoc(),
- DS.getRestrictSpecLoc()),
+ DS.getRestrictSpecLoc(),
+ DS.getAtomicSpecLoc()),
DS.getAttributes(),
SourceLocation());
else
@@ -4916,7 +5060,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
}
if (D.getCXXScopeSpec().isValid()) {
- if (Actions.ShouldEnterDeclaratorScope(getCurScope(), D.getCXXScopeSpec()))
+ if (Actions.ShouldEnterDeclaratorScope(getCurScope(),
+ D.getCXXScopeSpec()))
// Change the declaration context for name lookup, until this function
// is exited (and the declarator has been parsed).
DeclScopeObj.EnterDeclaratorScope();
@@ -4953,8 +5098,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// the l_paren token.
}
- if (Tok.is(tok::identifier) || Tok.is(tok::kw_operator) ||
- Tok.is(tok::annot_template_id) || Tok.is(tok::tilde)) {
+ if (Tok.isOneOf(tok::identifier, tok::kw_operator, tok::annot_template_id,
+ tok::tilde)) {
// We found something that indicates the start of an unqualified-id.
// Parse that unqualified-id.
bool AllowConstructorName;
@@ -4968,6 +5113,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
AllowConstructorName = (D.getContext() == Declarator::MemberContext);
SourceLocation TemplateKWLoc;
+ bool HadScope = D.getCXXScopeSpec().isValid();
if (ParseUnqualifiedId(D.getCXXScopeSpec(),
/*EnteringContext=*/true,
/*AllowDestructorName=*/true,
@@ -4981,6 +5127,13 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
D.SetIdentifier(nullptr, Tok.getLocation());
D.setInvalidType(true);
} else {
+ // ParseUnqualifiedId might have parsed a scope specifier during error
+ // recovery. If it did so, enter that scope.
+ if (!HadScope && D.getCXXScopeSpec().isValid() &&
+ Actions.ShouldEnterDeclaratorScope(getCurScope(),
+ D.getCXXScopeSpec()))
+ DeclScopeObj.EnterDeclaratorScope();
+
// Parsed the unqualified-id; update range information and move along.
if (D.getSourceRange().getBegin().isInvalid())
D.SetRangeBegin(D.getName().getSourceRange().getBegin());
@@ -5022,7 +5175,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// If there was an error parsing parenthesized declarator, declarator
// scope may have been entered before. Don't do it again.
if (!D.isInvalidType() &&
- Actions.ShouldEnterDeclaratorScope(getCurScope(), D.getCXXScopeSpec()))
+ Actions.ShouldEnterDeclaratorScope(getCurScope(),
+ D.getCXXScopeSpec()))
// Change the declaration context for name lookup, until this function
// is exited (and the declarator has been parsed).
DeclScopeObj.EnterDeclaratorScope();
@@ -5048,7 +5202,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
<< (D.getDeclSpec().isEmpty() ? SourceRange()
: D.getDeclSpec().getSourceRange());
} else if (getLangOpts().CPlusPlus) {
- if (Tok.is(tok::period) || Tok.is(tok::arrow))
+ if (Tok.isOneOf(tok::period, tok::arrow))
Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
else {
SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
@@ -5310,7 +5464,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
if (getLangOpts().CPlusPlus) {
// FIXME: Accept these components in any order, and produce fixits to
// correct the order if the user gets it wrong. Ideally we should deal
- // with the virt-specifier-seq and pure-specifier in the same way.
+ // with the pure-specifier in the same way.
// Parse cv-qualifier-seq[opt].
ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed,
@@ -5323,15 +5477,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
}
// Parse ref-qualifier[opt].
- if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) {
- Diag(Tok, getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_ref_qualifier :
- diag::ext_ref_qualifier);
-
- RefQualifierIsLValueRef = Tok.is(tok::amp);
- RefQualifierLoc = ConsumeToken();
+ if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc))
EndLoc = RefQualifierLoc;
- }
// C++11 [expr.prim.general]p3:
// If a declaration declares a member function or member function
@@ -5427,6 +5574,22 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
FnAttrs, EndLoc);
}
+/// ParseRefQualifier - Parses a member function ref-qualifier. Returns
+/// true if a ref-qualifier is found.
+bool Parser::ParseRefQualifier(bool &RefQualifierIsLValueRef,
+ SourceLocation &RefQualifierLoc) {
+ if (Tok.isOneOf(tok::amp, tok::ampamp)) {
+ Diag(Tok, getLangOpts().CPlusPlus11 ?
+ diag::warn_cxx98_compat_ref_qualifier :
+ diag::ext_ref_qualifier);
+
+ RefQualifierIsLValueRef = Tok.is(tok::amp);
+ RefQualifierLoc = ConsumeToken();
+ return true;
+ }
+ return false;
+}
+
/// isFunctionDeclaratorIdentifierList - This parameter list may have an
/// identifier list form for a K&R-style function: void foo(a,b,c)
///
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
index 87d9909..47778b8 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
@@ -558,6 +558,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
// Maybe this is an alias-declaration.
TypeResult TypeAlias;
bool IsAliasDecl = Tok.is(tok::equal);
+ Decl *DeclFromDeclSpec = nullptr;
if (IsAliasDecl) {
// If we had any misplaced attributes from earlier, this is where they
// should have been written.
@@ -612,10 +613,12 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
Diag(SS.getBeginLoc(), diag::err_alias_declaration_not_identifier)
<< FixItHint::CreateRemoval(SS.getRange());
- TypeAlias = ParseTypeName(nullptr, TemplateInfo.Kind ?
- Declarator::AliasTemplateContext :
- Declarator::AliasDeclContext, AS, OwnedType,
- &Attrs);
+ TypeAlias = ParseTypeName(nullptr, TemplateInfo.Kind
+ ? Declarator::AliasTemplateContext
+ : Declarator::AliasDeclContext,
+ AS, &DeclFromDeclSpec, &Attrs);
+ if (OwnedType)
+ *OwnedType = DeclFromDeclSpec;
} else {
// C++11 attributes are not allowed on a using-declaration, but GNU ones
// are.
@@ -664,7 +667,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
TemplateParams ? TemplateParams->size() : 0);
return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg,
UsingLoc, Name, Attrs.getList(),
- TypeAlias);
+ TypeAlias, DeclFromDeclSpec);
}
return Actions.ActOnUsingDeclaration(getCurScope(), AS,
@@ -682,7 +685,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
/// _Static_assert ( constant-expression , string-literal ) ;
///
Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
- assert((Tok.is(tok::kw_static_assert) || Tok.is(tok::kw__Static_assert)) &&
+ assert(Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert) &&
"Not a static_assert declaration");
if (Tok.is(tok::kw__Static_assert) && !getLangOpts().C11)
@@ -750,7 +753,7 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
/// 'decltype' ( 'auto' ) [C++1y]
///
SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
- assert((Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype))
+ assert(Tok.isOneOf(tok::kw_decltype, tok::annot_decltype)
&& "Not a decltype specifier");
ExprResult Result;
@@ -796,7 +799,10 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
// The operand of the decltype specifier is an unevaluated operand.
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
nullptr,/*IsDecltype=*/true);
- Result = Actions.CorrectDelayedTyposInExpr(ParseExpression());
+ Result =
+ Actions.CorrectDelayedTyposInExpr(ParseExpression(), [](Expr *E) {
+ return E->hasPlaceholderType() ? ExprError() : E;
+ });
if (Result.isInvalid()) {
DS.SetTypeSpecError();
if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) {
@@ -937,7 +943,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
// Parse decltype-specifier
// tok == kw_decltype is just error recovery, it can only happen when SS
// isn't empty
- if (Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype)) {
+ if (Tok.isOneOf(tok::kw_decltype, tok::annot_decltype)) {
if (SS.isNotEmpty())
Diag(SS.getBeginLoc(), diag::err_unexpected_scope_on_base_decltype)
<< FixItHint::CreateRemoval(SS.getRange());
@@ -1052,9 +1058,9 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
}
void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) {
- while (Tok.is(tok::kw___single_inheritance) ||
- Tok.is(tok::kw___multiple_inheritance) ||
- Tok.is(tok::kw___virtual_inheritance)) {
+ while (Tok.isOneOf(tok::kw___single_inheritance,
+ tok::kw___multiple_inheritance,
+ tok::kw___virtual_inheritance)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
@@ -1223,15 +1229,12 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
ParsedAttributesWithRange attrs(AttrFactory);
// If attributes exist after tag, parse them.
MaybeParseGNUAttributes(attrs);
-
- // If declspecs exist after tag, parse them.
- while (Tok.is(tok::kw___declspec))
- ParseMicrosoftDeclSpec(attrs);
+ MaybeParseMicrosoftDeclSpecs(attrs);
// Parse inheritance specifiers.
- if (Tok.is(tok::kw___single_inheritance) ||
- Tok.is(tok::kw___multiple_inheritance) ||
- Tok.is(tok::kw___virtual_inheritance))
+ if (Tok.isOneOf(tok::kw___single_inheritance,
+ tok::kw___multiple_inheritance,
+ tok::kw___virtual_inheritance))
ParseMicrosoftInheritanceClassAttributes(attrs);
// If C++0x attributes exist here, parse them.
@@ -1247,55 +1250,55 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
Tok.isNot(tok::identifier) &&
!Tok.isAnnotation() &&
Tok.getIdentifierInfo() &&
- (Tok.is(tok::kw___is_abstract) ||
- Tok.is(tok::kw___is_arithmetic) ||
- Tok.is(tok::kw___is_array) ||
- Tok.is(tok::kw___is_base_of) ||
- Tok.is(tok::kw___is_class) ||
- Tok.is(tok::kw___is_complete_type) ||
- Tok.is(tok::kw___is_compound) ||
- Tok.is(tok::kw___is_const) ||
- Tok.is(tok::kw___is_constructible) ||
- Tok.is(tok::kw___is_convertible) ||
- Tok.is(tok::kw___is_convertible_to) ||
- Tok.is(tok::kw___is_destructible) ||
- Tok.is(tok::kw___is_empty) ||
- Tok.is(tok::kw___is_enum) ||
- Tok.is(tok::kw___is_floating_point) ||
- Tok.is(tok::kw___is_final) ||
- Tok.is(tok::kw___is_function) ||
- Tok.is(tok::kw___is_fundamental) ||
- Tok.is(tok::kw___is_integral) ||
- Tok.is(tok::kw___is_interface_class) ||
- Tok.is(tok::kw___is_literal) ||
- Tok.is(tok::kw___is_lvalue_expr) ||
- Tok.is(tok::kw___is_lvalue_reference) ||
- Tok.is(tok::kw___is_member_function_pointer) ||
- Tok.is(tok::kw___is_member_object_pointer) ||
- Tok.is(tok::kw___is_member_pointer) ||
- Tok.is(tok::kw___is_nothrow_assignable) ||
- Tok.is(tok::kw___is_nothrow_constructible) ||
- Tok.is(tok::kw___is_nothrow_destructible) ||
- Tok.is(tok::kw___is_object) ||
- Tok.is(tok::kw___is_pod) ||
- Tok.is(tok::kw___is_pointer) ||
- Tok.is(tok::kw___is_polymorphic) ||
- Tok.is(tok::kw___is_reference) ||
- Tok.is(tok::kw___is_rvalue_expr) ||
- Tok.is(tok::kw___is_rvalue_reference) ||
- Tok.is(tok::kw___is_same) ||
- Tok.is(tok::kw___is_scalar) ||
- Tok.is(tok::kw___is_sealed) ||
- Tok.is(tok::kw___is_signed) ||
- Tok.is(tok::kw___is_standard_layout) ||
- Tok.is(tok::kw___is_trivial) ||
- Tok.is(tok::kw___is_trivially_assignable) ||
- Tok.is(tok::kw___is_trivially_constructible) ||
- Tok.is(tok::kw___is_trivially_copyable) ||
- Tok.is(tok::kw___is_union) ||
- Tok.is(tok::kw___is_unsigned) ||
- Tok.is(tok::kw___is_void) ||
- Tok.is(tok::kw___is_volatile)))
+ Tok.isOneOf(tok::kw___is_abstract,
+ tok::kw___is_arithmetic,
+ tok::kw___is_array,
+ tok::kw___is_base_of,
+ tok::kw___is_class,
+ tok::kw___is_complete_type,
+ tok::kw___is_compound,
+ tok::kw___is_const,
+ tok::kw___is_constructible,
+ tok::kw___is_convertible,
+ tok::kw___is_convertible_to,
+ tok::kw___is_destructible,
+ tok::kw___is_empty,
+ tok::kw___is_enum,
+ tok::kw___is_floating_point,
+ tok::kw___is_final,
+ tok::kw___is_function,
+ tok::kw___is_fundamental,
+ tok::kw___is_integral,
+ tok::kw___is_interface_class,
+ tok::kw___is_literal,
+ tok::kw___is_lvalue_expr,
+ tok::kw___is_lvalue_reference,
+ tok::kw___is_member_function_pointer,
+ tok::kw___is_member_object_pointer,
+ tok::kw___is_member_pointer,
+ tok::kw___is_nothrow_assignable,
+ tok::kw___is_nothrow_constructible,
+ tok::kw___is_nothrow_destructible,
+ tok::kw___is_object,
+ tok::kw___is_pod,
+ tok::kw___is_pointer,
+ tok::kw___is_polymorphic,
+ tok::kw___is_reference,
+ tok::kw___is_rvalue_expr,
+ tok::kw___is_rvalue_reference,
+ tok::kw___is_same,
+ tok::kw___is_scalar,
+ tok::kw___is_sealed,
+ tok::kw___is_signed,
+ tok::kw___is_standard_layout,
+ tok::kw___is_trivial,
+ tok::kw___is_trivially_assignable,
+ tok::kw___is_trivially_constructible,
+ tok::kw___is_trivially_copyable,
+ tok::kw___is_union,
+ tok::kw___is_unsigned,
+ tok::kw___is_void,
+ tok::kw___is_volatile))
// GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the
// name of struct templates, but some are keywords in GCC >= 4.3
// and Clang. Therefore, when we see the token sequence "struct
@@ -1310,11 +1313,19 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// is a base-specifier-list.
ColonProtectionRAIIObject X(*this);
- if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext))
+ CXXScopeSpec Spec;
+ bool HasValidSpec = true;
+ if (ParseOptionalCXXScopeSpecifier(Spec, ParsedType(), EnteringContext)) {
DS.SetTypeSpecError();
- if (SS.isSet())
- if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
+ HasValidSpec = false;
+ }
+ if (Spec.isSet())
+ if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) {
Diag(Tok, diag::err_expected) << tok::identifier;
+ HasValidSpec = false;
+ }
+ if (HasValidSpec)
+ SS = Spec;
}
TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
@@ -1465,7 +1476,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
}
}
- if (Tok.is(tok::l_brace) || Tok.is(tok::colon))
+ if (Tok.isOneOf(tok::l_brace, tok::colon))
TUK = Sema::TUK_Definition;
else
TUK = Sema::TUK_Reference;
@@ -1539,6 +1550,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TypeResult TypeResult = true; // invalid
bool Owned = false;
+ Sema::SkipBodyInfo SkipBody;
if (TemplateId) {
// Explicit specialization, class template partial specialization,
// or explicit instantiation.
@@ -1625,7 +1637,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
*TemplateId, attrs.getList(),
MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0]
: nullptr,
- TemplateParams ? TemplateParams->size() : 0));
+ TemplateParams ? TemplateParams->size() : 0),
+ &SkipBody);
}
} else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
TUK == Sema::TUK_Declaration) {
@@ -1677,6 +1690,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TParams =
MultiTemplateParamsArg(&(*TemplateParams)[0], TemplateParams->size());
+ handleDeclspecAlignBeforeClassKey(attrs, DS, TUK);
+
// Declaration or definition of a class type
TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, TUK, StartLoc,
SS, Name, NameLoc, attrs.getList(), AS,
@@ -1684,7 +1699,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TParams, Owned, IsDependent,
SourceLocation(), false,
clang::TypeResult(),
- DSC == DSC_type_specifier);
+ DSC == DSC_type_specifier,
+ &SkipBody);
// If ActOnTag said the type was dependent, try again with the
// less common call.
@@ -1700,7 +1716,10 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
assert(Tok.is(tok::l_brace) ||
(getLangOpts().CPlusPlus && Tok.is(tok::colon)) ||
isCXX11FinalKeyword());
- if (getLangOpts().CPlusPlus)
+ if (SkipBody.ShouldSkip)
+ SkipCXXMemberSpecification(StartLoc, AttrFixitLoc, TagType,
+ TagOrTempResult.get());
+ else if (getLangOpts().CPlusPlus)
ParseCXXMemberSpecification(StartLoc, AttrFixitLoc, attrs, TagType,
TagOrTempResult.get());
else
@@ -1882,51 +1901,40 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const {
/// the class definition.
void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
Decl *ThisDecl) {
- // We just declared a member function. If this member function
- // has any default arguments or an exception-specification, we'll need to
- // parse them later.
- LateParsedMethodDeclaration *LateMethod = nullptr;
DeclaratorChunk::FunctionTypeInfo &FTI
= DeclaratorInfo.getFunctionTypeInfo();
+ // If there was a late-parsed exception-specification, we'll need a
+ // late parse
+ bool NeedLateParse = FTI.getExceptionSpecType() == EST_Unparsed;
+
+ if (!NeedLateParse) {
+ // Look ahead to see if there are any default args
+ for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) {
+ auto Param = cast<ParmVarDecl>(FTI.Params[ParamIdx].Param);
+ if (Param->hasUnparsedDefaultArg()) {
+ NeedLateParse = true;
+ break;
+ }
+ }
+ }
- // If there was a late-parsed exception-specification, hold onto its tokens.
- if (FTI.getExceptionSpecType() == EST_Unparsed) {
+ if (NeedLateParse) {
// Push this method onto the stack of late-parsed method
// declarations.
- LateMethod = new LateParsedMethodDeclaration(this, ThisDecl);
+ auto LateMethod = new LateParsedMethodDeclaration(this, ThisDecl);
getCurrentClass().LateParsedDeclarations.push_back(LateMethod);
LateMethod->TemplateScope = getCurScope()->isTemplateParamScope();
- // Stash the exception-specification tokens in the late-pased mthod.
+ // Stash the exception-specification tokens in the late-pased method.
LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens;
FTI.ExceptionSpecTokens = 0;
- // Reserve space for the parameters.
+ // Push tokens for each parameter. Those that do not have
+ // defaults will be NULL.
LateMethod->DefaultArgs.reserve(FTI.NumParams);
- }
-
- for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) {
- if (LateMethod || FTI.Params[ParamIdx].DefaultArgTokens) {
- if (!LateMethod) {
- // Push this method onto the stack of late-parsed method
- // declarations.
- LateMethod = new LateParsedMethodDeclaration(this, ThisDecl);
- getCurrentClass().LateParsedDeclarations.push_back(LateMethod);
- LateMethod->TemplateScope = getCurScope()->isTemplateParamScope();
-
- // Add all of the parameters prior to this one (they don't
- // have default arguments).
- LateMethod->DefaultArgs.reserve(FTI.NumParams);
- for (unsigned I = 0; I < ParamIdx; ++I)
- LateMethod->DefaultArgs.push_back(
- LateParsedDefaultArgument(FTI.Params[I].Param));
- }
-
- // Add this parameter to the list of parameters (it may or may
- // not have a default argument).
+ for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx)
LateMethod->DefaultArgs.push_back(LateParsedDefaultArgument(
- FTI.Params[ParamIdx].Param, FTI.Params[ParamIdx].DefaultArgTokens));
- }
+ FTI.Params[ParamIdx].Param, FTI.Params[ParamIdx].DefaultArgTokens));
}
}
@@ -2019,7 +2027,7 @@ bool Parser::isCXX11FinalKeyword() const {
/// \brief Parse a C++ member-declarator up to, but not including, the optional
/// brace-or-equal-initializer or pure-specifier.
-void Parser::ParseCXXMemberDeclaratorBeforeInitializer(
+bool Parser::ParseCXXMemberDeclaratorBeforeInitializer(
Declarator &DeclaratorInfo, VirtSpecifiers &VS, ExprResult &BitfieldSize,
LateParsedAttrList &LateParsedAttrs) {
// member-declarator:
@@ -2037,10 +2045,13 @@ void Parser::ParseCXXMemberDeclaratorBeforeInitializer(
BitfieldSize = ParseConstantExpression();
if (BitfieldSize.isInvalid())
SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
- } else
+ } else {
ParseOptionalCXX11VirtSpecifierSeq(
VS, getCurrentClass().IsInterface,
DeclaratorInfo.getDeclSpec().getFriendSpecLoc());
+ if (!VS.isUnset())
+ MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, VS);
+ }
// If a simple-asm-expr is present, parse it.
if (Tok.is(tok::kw_asm)) {
@@ -2071,6 +2082,78 @@ void Parser::ParseCXXMemberDeclaratorBeforeInitializer(
Diag(Attr->getLoc(), diag::warn_gcc_attribute_location);
Attr = Attr->getNext();
}
+ MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, VS);
+ }
+ }
+
+ // If this has neither a name nor a bit width, something has gone seriously
+ // wrong. Skip until the semi-colon or }.
+ if (!DeclaratorInfo.hasName() && BitfieldSize.isUnset()) {
+ // If so, skip until the semi-colon or a }.
+ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
+ return true;
+ }
+ return false;
+}
+
+/// \brief Look for declaration specifiers possibly occurring after C++11
+/// virt-specifier-seq and diagnose them.
+void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(
+ Declarator &D,
+ VirtSpecifiers &VS) {
+ DeclSpec DS(AttrFactory);
+
+ // GNU-style and C++11 attributes are not allowed here, but they will be
+ // handled by the caller. Diagnose everything else.
+ ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed, false);
+ D.ExtendWithDeclSpec(DS);
+
+ if (D.isFunctionDeclarator()) {
+ auto &Function = D.getFunctionTypeInfo();
+ if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {
+ auto DeclSpecCheck = [&] (DeclSpec::TQ TypeQual,
+ const char *FixItName,
+ SourceLocation SpecLoc,
+ unsigned* QualifierLoc) {
+ FixItHint Insertion;
+ if (DS.getTypeQualifiers() & TypeQual) {
+ if (!(Function.TypeQuals & TypeQual)) {
+ std::string Name(FixItName);
+ Name += " ";
+ Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name.c_str());
+ Function.TypeQuals |= TypeQual;
+ *QualifierLoc = SpecLoc.getRawEncoding();
+ }
+ Diag(SpecLoc, diag::err_declspec_after_virtspec)
+ << FixItName
+ << VirtSpecifiers::getSpecifierName(VS.getLastSpecifier())
+ << FixItHint::CreateRemoval(SpecLoc)
+ << Insertion;
+ }
+ };
+ DeclSpecCheck(DeclSpec::TQ_const, "const", DS.getConstSpecLoc(),
+ &Function.ConstQualifierLoc);
+ DeclSpecCheck(DeclSpec::TQ_volatile, "volatile", DS.getVolatileSpecLoc(),
+ &Function.VolatileQualifierLoc);
+ DeclSpecCheck(DeclSpec::TQ_restrict, "restrict", DS.getRestrictSpecLoc(),
+ &Function.RestrictQualifierLoc);
+ }
+
+ // Parse ref-qualifiers.
+ bool RefQualifierIsLValueRef = true;
+ SourceLocation RefQualifierLoc;
+ if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc)) {
+ const char *Name = (RefQualifierIsLValueRef ? "& " : "&& ");
+ FixItHint Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name);
+ Function.RefQualifierIsLValueRef = RefQualifierIsLValueRef;
+ Function.RefQualifierLoc = RefQualifierLoc.getRawEncoding();
+
+ Diag(RefQualifierLoc, diag::err_declspec_after_virtspec)
+ << (RefQualifierIsLValueRef ? "&" : "&&")
+ << VirtSpecifiers::getSpecifierName(VS.getLastSpecifier())
+ << FixItHint::CreateRemoval(RefQualifierLoc)
+ << Insertion;
+ D.SetRangeEnd(RefQualifierLoc);
}
}
}
@@ -2137,8 +2220,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// Access declarations.
bool MalformedTypeSpec = false;
if (!TemplateInfo.Kind &&
- (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
- Tok.is(tok::kw___super))) {
+ Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw___super)) {
if (TryAnnotateCXXScopeToken())
MalformedTypeSpec = true;
@@ -2191,7 +2273,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// static_assert-declaration. A templated static_assert declaration is
// diagnosed in Parser::ParseSingleDeclarationAfterTemplate.
if (!TemplateInfo.Kind &&
- (Tok.is(tok::kw_static_assert) || Tok.is(tok::kw__Static_assert))) {
+ Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) {
SourceLocation DeclEnd;
ParseStaticAssertDeclaration(DeclEnd);
return;
@@ -2298,14 +2380,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
bool ExpectSemi = true;
// Parse the first declarator.
- ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize,
- LateParsedAttrs);
-
- // If this has neither a name nor a bit width, something has gone seriously
- // wrong. Skip until the semi-colon or }.
- if (!DeclaratorInfo.hasName() && BitfieldSize.isUnset()) {
- // If so, skip until the semi-colon or a }.
- SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
+ if (ParseCXXMemberDeclaratorBeforeInitializer(
+ DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs)) {
TryConsumeToken(tok::semi);
return;
}
@@ -2334,7 +2410,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (Tok.is(tok::l_brace) && !getLangOpts().CPlusPlus11) {
DefinitionKind = FDK_Definition;
} else if (DeclaratorInfo.isFunctionDeclarator()) {
- if (Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) {
+ if (Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try)) {
DefinitionKind = FDK_Definition;
} else if (Tok.is(tok::equal)) {
const Token &KW = NextToken();
@@ -2344,6 +2420,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
DefinitionKind = FDK_Deleted;
}
}
+ DeclaratorInfo.setFunctionDefinitionKind(DefinitionKind);
// C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains
// to a friend declaration, that declaration shall be a definition.
@@ -2354,7 +2431,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
ProhibitAttributes(FnAttrs);
}
- if (DefinitionKind) {
+ if (DefinitionKind != FDK_Declaration) {
if (!DeclaratorInfo.isFunctionDeclarator()) {
Diag(DeclaratorInfo.getIdentifierLoc(), diag::err_func_def_no_params);
ConsumeBrace();
@@ -2376,7 +2453,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
Decl *FunDecl =
ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo, TemplateInfo,
- VS, DefinitionKind, Init);
+ VS, Init);
if (FunDecl) {
for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) {
@@ -2402,7 +2479,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
while (1) {
InClassInitStyle HasInClassInit = ICIS_NoInit;
- if ((Tok.is(tok::equal) || Tok.is(tok::l_brace)) && !HasInitializer) {
+ if (Tok.isOneOf(tok::equal, tok::l_brace) && !HasInitializer) {
if (BitfieldSize.get()) {
Diag(Tok, diag::err_bitfield_member_init);
SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
@@ -2530,16 +2607,17 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// Parse the next declarator.
DeclaratorInfo.clear();
VS.clear();
- BitfieldSize = true;
- Init = true;
+ BitfieldSize = ExprResult(/*Invalid=*/false);
+ Init = ExprResult(/*Invalid=*/false);
HasInitializer = false;
DeclaratorInfo.setCommaLoc(CommaLoc);
// GNU attributes are allowed before the second and subsequent declarator.
MaybeParseGNUAttributes(DeclaratorInfo);
- ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize,
- LateParsedAttrs);
+ if (ParseCXXMemberDeclaratorBeforeInitializer(
+ DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs))
+ break;
}
if (ExpectSemi &&
@@ -2578,7 +2656,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
/// be a constant-expression.
ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,
SourceLocation &EqualLoc) {
- assert((Tok.is(tok::equal) || Tok.is(tok::l_brace))
+ assert(Tok.isOneOf(tok::equal, tok::l_brace)
&& "Data member initializer not starting with '=' or '{'");
EnterExpressionEvaluationContext Context(Actions,
@@ -2592,8 +2670,7 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,
// An initializer of '= delete p, foo' will never be parsed, because
// a top-level comma always ends the initializer expression.
const Token &Next = NextToken();
- if (IsFunction || Next.is(tok::semi) || Next.is(tok::comma) ||
- Next.is(tok::eof)) {
+ if (IsFunction || Next.isOneOf(tok::semi, tok::comma, tok::eof)) {
if (IsFunction)
Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
<< 1 /* delete */;
@@ -2617,6 +2694,56 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,
return ParseInitializer();
}
+void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc,
+ SourceLocation AttrFixitLoc,
+ unsigned TagType, Decl *TagDecl) {
+ // Skip the optional 'final' keyword.
+ if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) {
+ assert(isCXX11FinalKeyword() && "not a class definition");
+ ConsumeToken();
+
+ // Diagnose any C++11 attributes after 'final' keyword.
+ // We deliberately discard these attributes.
+ ParsedAttributesWithRange Attrs(AttrFactory);
+ CheckMisplacedCXX11Attribute(Attrs, AttrFixitLoc);
+
+ // This can only happen if we had malformed misplaced attributes;
+ // we only get called if there is a colon or left-brace after the
+ // attributes.
+ if (Tok.isNot(tok::colon) && Tok.isNot(tok::l_brace))
+ return;
+ }
+
+ // Skip the base clauses. This requires actually parsing them, because
+ // otherwise we can't be sure where they end (a left brace may appear
+ // within a template argument).
+ if (Tok.is(tok::colon)) {
+ // Enter the scope of the class so that we can correctly parse its bases.
+ ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope);
+ ParsingClassDefinition ParsingDef(*this, TagDecl, /*NonNestedClass*/ true,
+ TagType == DeclSpec::TST_interface);
+ auto OldContext =
+ Actions.ActOnTagStartSkippedDefinition(getCurScope(), TagDecl);
+
+ // Parse the bases but don't attach them to the class.
+ ParseBaseClause(nullptr);
+
+ Actions.ActOnTagFinishSkippedDefinition(OldContext);
+
+ if (!Tok.is(tok::l_brace)) {
+ Diag(PP.getLocForEndOfToken(PrevTokLocation),
+ diag::err_expected_lbrace_after_base_specifiers);
+ return;
+ }
+ }
+
+ // Skip the body.
+ assert(Tok.is(tok::l_brace));
+ BalancedDelimiterTracker T(*this, tok::l_brace);
+ T.consumeOpen();
+ T.skipToEnd();
+}
+
/// ParseCXXMemberSpecification - Parse the class definition.
///
/// member-specification:
@@ -2787,8 +2914,8 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
// Each iteration of this loop reads one member-declaration.
- if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) ||
- Tok.is(tok::kw___if_not_exists))) {
+ if (getLangOpts().MicrosoftExt && Tok.isOneOf(tok::kw___if_exists,
+ tok::kw___if_not_exists)) {
ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS);
continue;
}
@@ -2911,6 +3038,10 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
ParseLexedMemberInitializers(getCurrentClass());
ParseLexedMethodDefs(getCurrentClass());
PrevTokLocation = SavedPrevTokLocation;
+
+ // We've finished parsing everything, including default argument
+ // initializers.
+ Actions.ActOnFinishCXXMemberDefaultArgs(TagDecl);
}
if (TagDecl)
@@ -2965,9 +3096,11 @@ void Parser::DiagnoseUnexpectedNamespace(NamedDecl *D) {
/// mem-initializer ...[opt]
/// mem-initializer ...[opt] , mem-initializer-list
void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {
- assert(Tok.is(tok::colon) && "Constructor initializer always starts with ':'");
+ assert(Tok.is(tok::colon) &&
+ "Constructor initializer always starts with ':'");
- // Poison the SEH identifiers so they are flagged as illegal in constructor initializers
+ // Poison the SEH identifiers so they are flagged as illegal in constructor
+ // initializers.
PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true);
SourceLocation ColonLoc = ConsumeToken();
@@ -2993,7 +3126,7 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {
break;
// If the next token looks like a base or member initializer, assume that
// we're just missing a comma.
- else if (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) {
+ else if (Tok.isOneOf(tok::identifier, tok::coloncolon)) {
SourceLocation Loc = PP.getLocForEndOfToken(PrevTokLocation);
Diag(Loc, diag::err_ctor_init_missing_comma)
<< FixItHint::CreateInsertion(Loc, ", ");
@@ -3396,7 +3529,9 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) {
// Alternative tokens do not have identifier info, but their spelling
// starts with an alphabetical character.
SmallString<8> SpellingBuf;
- StringRef Spelling = PP.getSpelling(Tok.getLocation(), SpellingBuf);
+ SourceLocation SpellingLoc =
+ PP.getSourceManager().getSpellingLoc(Tok.getLocation());
+ StringRef Spelling = PP.getSpelling(SpellingLoc, SpellingBuf);
if (isLetter(Spelling[0])) {
Loc = ConsumeToken();
return &PP.getIdentifierTable().get(Spelling);
@@ -3474,7 +3609,6 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
// The attribute was allowed to have arguments, but none were provided
// even though the attribute parsed successfully. This is an error.
Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName;
- return false;
} else if (!Attr->getMaxArgs()) {
// The attribute parsed successfully, but was not allowed to have any
// arguments. It doesn't matter whether any were provided -- the
@@ -3482,7 +3616,6 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments)
<< AttrName
<< FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc));
- return false;
}
}
}
@@ -3645,7 +3778,7 @@ SourceLocation Parser::SkipCXX11Attributes() {
return EndLoc;
}
-/// ParseMicrosoftAttributes - Parse a Microsoft attribute [Attr]
+/// Parse one or more Microsoft-style attributes [Attr]
///
/// [MS] ms-attribute:
/// '[' token-seq ']'
@@ -3657,13 +3790,17 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs,
SourceLocation *endLoc) {
assert(Tok.is(tok::l_square) && "Not a Microsoft attribute list");
- while (Tok.is(tok::l_square)) {
+ do {
// FIXME: If this is actually a C++11 attribute, parse it as one.
- ConsumeBracket();
+ BalancedDelimiterTracker T(*this, tok::l_square);
+ T.consumeOpen();
+ if (Tok.is(tok::r_square))
+ Diag(T.getOpenLocation(), diag::err_empty_attribute_block);
SkipUntil(tok::r_square, StopAtSemi | StopBeforeMatch);
- if (endLoc) *endLoc = Tok.getLocation();
- ExpectAndConsume(tok::r_square);
- }
+ T.consumeClose();
+ if (endLoc)
+ *endLoc = T.getCloseLocation();
+ } while (Tok.is(tok::l_square));
}
void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
@@ -3695,7 +3832,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
// __if_exists, __if_not_exists can nest.
- if ((Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists))) {
+ if (Tok.isOneOf(tok::kw___if_exists, tok::kw___if_not_exists)) {
ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS);
continue;
}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp
index d0d97de..da759c7 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp
@@ -347,7 +347,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
RHS = ParseCastExpression(false);
if (RHS.isInvalid()) {
+ // FIXME: Errors generated by the delayed typo correction should be
+ // printed before errors from parsing the RHS, not after.
Actions.CorrectDelayedTyposInExpr(LHS);
+ if (TernaryMiddle.isUsable())
+ TernaryMiddle = Actions.CorrectDelayedTyposInExpr(TernaryMiddle);
LHS = ExprError();
}
@@ -380,7 +384,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
RHSIsInitList = false;
if (RHS.isInvalid()) {
+ // FIXME: Errors generated by the delayed typo correction should be
+ // printed before errors from ParseRHSOfBinaryExpression, not after.
Actions.CorrectDelayedTyposInExpr(LHS);
+ if (TernaryMiddle.isUsable())
+ TernaryMiddle = Actions.CorrectDelayedTyposInExpr(TernaryMiddle);
LHS = ExprError();
}
@@ -446,8 +454,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
namespace {
class CastExpressionIdValidator : public CorrectionCandidateCallback {
public:
- CastExpressionIdValidator(bool AllowTypes, bool AllowNonTypes)
- : AllowNonTypes(AllowNonTypes) {
+ CastExpressionIdValidator(Token Next, bool AllowTypes, bool AllowNonTypes)
+ : NextToken(Next), AllowNonTypes(AllowNonTypes) {
WantTypeSpecifiers = WantFunctionLikeCasts = AllowTypes;
}
@@ -458,11 +466,23 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
if (isa<TypeDecl>(ND))
return WantTypeSpecifiers;
- return AllowNonTypes &&
- CorrectionCandidateCallback::ValidateCandidate(candidate);
+
+ if (!AllowNonTypes || !CorrectionCandidateCallback::ValidateCandidate(candidate))
+ return false;
+
+ if (!NextToken.isOneOf(tok::equal, tok::arrow, tok::period))
+ return true;
+
+ for (auto *C : candidate) {
+ NamedDecl *ND = C->getUnderlyingDecl();
+ if (isa<ValueDecl>(ND) && !isa<FunctionDecl>(ND))
+ return true;
+ }
+ return false;
}
private:
+ Token NextToken;
bool AllowNonTypes;
};
}
@@ -808,11 +828,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
}
}
- if (Next.is(tok::coloncolon) ||
- (!ColonIsSacred && Next.is(tok::colon)) ||
- Next.is(tok::less) ||
- Next.is(tok::l_paren) ||
- Next.is(tok::l_brace)) {
+ if ((!ColonIsSacred && Next.is(tok::colon)) ||
+ Next.isOneOf(tok::coloncolon, tok::less, tok::l_paren,
+ tok::l_brace)) {
// If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.
if (TryAnnotateTypeOrScopeToken())
return ExprError();
@@ -908,14 +926,20 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
SourceLocation TemplateKWLoc;
Token Replacement;
auto Validator = llvm::make_unique<CastExpressionIdValidator>(
- isTypeCast != NotTypeCast, isTypeCast != IsTypeCast);
+ Tok, isTypeCast != NotTypeCast, isTypeCast != IsTypeCast);
Validator->IsAddressOfOperand = isAddressOfOperand;
- Validator->WantRemainingKeywords = Tok.isNot(tok::r_paren);
+ if (Tok.isOneOf(tok::periodstar, tok::arrowstar)) {
+ Validator->WantExpressionKeywords = false;
+ Validator->WantRemainingKeywords = false;
+ } else {
+ Validator->WantRemainingKeywords = Tok.isNot(tok::r_paren);
+ }
Name.setIdentifier(&II, ILoc);
Res = Actions.ActOnIdExpression(
getCurScope(), ScopeSpec, TemplateKWLoc, Name, Tok.is(tok::l_paren),
isAddressOfOperand, std::move(Validator),
- /*IsInlineAsmIdentifier=*/false, &Replacement);
+ /*IsInlineAsmIdentifier=*/false,
+ Tok.is(tok::r_paren) ? nullptr : &Replacement);
if (!Res.isInvalid() && !Res.get()) {
UnconsumeToken(Replacement);
return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
@@ -1441,10 +1465,14 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
if (OpKind == tok::l_paren || !LHS.isInvalid()) {
if (Tok.isNot(tok::r_paren)) {
- if (ParseExpressionList(ArgExprs, CommaLocs, &Sema::CodeCompleteCall,
- LHS.get())) {
+ if (ParseExpressionList(ArgExprs, CommaLocs, [&] {
+ Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs);
+ })) {
(void)Actions.CorrectDelayedTyposInExpr(LHS);
LHS = ExprError();
+ } else if (LHS.isInvalid()) {
+ for (auto &E : ArgExprs)
+ Actions.CorrectDelayedTyposInExpr(E);
}
}
}
@@ -1453,7 +1481,19 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
if (LHS.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
} else if (Tok.isNot(tok::r_paren)) {
- PT.consumeClose();
+ bool HadDelayedTypo = false;
+ if (Actions.CorrectDelayedTyposInExpr(LHS).get() != LHS.get())
+ HadDelayedTypo = true;
+ for (auto &E : ArgExprs)
+ if (Actions.CorrectDelayedTyposInExpr(E).get() != E)
+ HadDelayedTypo = true;
+ // If there were delayed typos in the LHS or ArgExprs, call SkipUntil
+ // instead of PT.consumeClose() to avoid emitting extra diagnostics for
+ // the unmatched l_paren.
+ if (HadDelayedTypo)
+ SkipUntil(tok::r_paren, StopAtSemi);
+ else
+ PT.consumeClose();
LHS = ExprError();
} else {
assert((ArgExprs.size() == 0 ||
@@ -1510,14 +1550,14 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
cutOffParsing();
return ExprError();
}
-
+
if (MayBePseudoDestructor && !LHS.isInvalid()) {
LHS = ParseCXXPseudoDestructor(LHS.get(), OpLoc, OpKind, SS,
ObjectType);
break;
}
- // Either the action has told is that this cannot be a
+ // Either the action has told us that this cannot be a
// pseudo-destructor expression (based on the type of base
// expression), or we didn't see a '~' in the right place. We
// can still parse a destructor name here, but in that case it
@@ -1526,7 +1566,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
// FIXME: Add support for explicit call of template constructor.
SourceLocation TemplateKWLoc;
UnqualifiedId Name;
- if (getLangOpts().ObjC2 && OpKind == tok::period && Tok.is(tok::kw_class)) {
+ if (getLangOpts().ObjC2 && OpKind == tok::period &&
+ Tok.is(tok::kw_class)) {
// Objective-C++:
// After a '.' in a member access expression, treat the keyword
// 'class' as if it were an identifier.
@@ -1551,8 +1592,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc,
OpKind, SS, TemplateKWLoc, Name,
CurParsedObjCImpl ? CurParsedObjCImpl->Dcl
- : nullptr,
- Tok.is(tok::l_paren));
+ : nullptr);
break;
}
case tok::plusplus: // postfix-expression: postfix-expression '++'
@@ -1596,10 +1636,9 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
ParsedType &CastTy,
SourceRange &CastRange) {
- assert((OpTok.is(tok::kw_typeof) || OpTok.is(tok::kw_sizeof) ||
- OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof) ||
- OpTok.is(tok::kw__Alignof) || OpTok.is(tok::kw_vec_step)) &&
- "Not a typeof/sizeof/alignof/vec_step expression!");
+ assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_sizeof, tok::kw___alignof,
+ tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step) &&
+ "Not a typeof/sizeof/alignof/vec_step expression!");
ExprResult Operand;
@@ -1607,8 +1646,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
if (Tok.isNot(tok::l_paren)) {
// If construct allows a form without parenthesis, user may forget to put
// pathenthesis around type name.
- if (OpTok.is(tok::kw_sizeof) || OpTok.is(tok::kw___alignof) ||
- OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof)) {
+ if (OpTok.isOneOf(tok::kw_sizeof, tok::kw___alignof, tok::kw_alignof,
+ tok::kw__Alignof)) {
if (isTypeIdUnambiguously()) {
DeclSpec DS(AttrFactory);
ParseSpecifierQualifierList(DS);
@@ -1682,9 +1721,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
/// [C++11] 'alignof' '(' type-id ')'
/// \endverbatim
ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
- assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof) ||
- Tok.is(tok::kw_alignof) || Tok.is(tok::kw__Alignof) ||
- Tok.is(tok::kw_vec_step)) &&
+ assert(Tok.isOneOf(tok::kw_sizeof, tok::kw___alignof, tok::kw_alignof,
+ tok::kw__Alignof, tok::kw_vec_step) &&
"Not a sizeof/alignof/vec_step expression!");
Token OpTok = Tok;
ConsumeToken();
@@ -1735,7 +1773,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
RParenLoc);
}
- if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof))
+ if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof))
Diag(OpTok, diag::warn_cxx98_compat_alignof);
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
@@ -1750,8 +1788,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
CastRange);
UnaryExprOrTypeTrait ExprKind = UETT_SizeOf;
- if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw___alignof) ||
- OpTok.is(tok::kw__Alignof))
+ if (OpTok.isOneOf(tok::kw_alignof, tok::kw___alignof, tok::kw__Alignof))
ExprKind = UETT_AlignOf;
else if (OpTok.is(tok::kw_vec_step))
ExprKind = UETT_VecStep;
@@ -1763,7 +1800,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
CastTy.getAsOpaquePtr(),
CastRange);
- if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof))
+ if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof))
Diag(OpTok, diag::ext_alignof_expr) << OpTok.getIdentifierInfo();
// If we get here, the operand to the sizeof/alignof was an expresion.
@@ -2064,10 +2101,10 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// Diagnose use of bridge casts in non-arc mode.
bool BridgeCast = (getLangOpts().ObjC2 &&
- (Tok.is(tok::kw___bridge) ||
- Tok.is(tok::kw___bridge_transfer) ||
- Tok.is(tok::kw___bridge_retained) ||
- Tok.is(tok::kw___bridge_retain)));
+ Tok.isOneOf(tok::kw___bridge,
+ tok::kw___bridge_transfer,
+ tok::kw___bridge_retained,
+ tok::kw___bridge_retain));
if (BridgeCast && !getLangOpts().ObjCAutoRefCount) {
if (!TryConsumeToken(tok::kw___bridge)) {
StringRef BridgeCastName = Tok.getName();
@@ -2088,6 +2125,17 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
if (!getCurScope()->getFnParent() && !getCurScope()->getBlockParent()) {
Result = ExprError(Diag(OpenLoc, diag::err_stmtexpr_file_scope));
} else {
+ // Find the nearest non-record decl context. Variables declared in a
+ // statement expression behave as if they were declared in the enclosing
+ // function, block, or other code construct.
+ DeclContext *CodeDC = Actions.CurContext;
+ while (CodeDC->isRecord() || isa<EnumDecl>(CodeDC)) {
+ CodeDC = CodeDC->getParent();
+ assert(CodeDC && !CodeDC->isFileContext() &&
+ "statement expr not in code context");
+ }
+ Sema::ContextRAII SavedContext(Actions, CodeDC, /*NewThisContext=*/false);
+
Actions.ActOnStartStmtExpr();
StmtResult Stmt(ParseCompoundStatement(true));
@@ -2256,6 +2304,11 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
InMessageExpressionRAIIObject InMessage(*this, false);
Result = ParseExpression(MaybeTypeCast);
+ if (!getLangOpts().CPlusPlus && MaybeTypeCast && Result.isUsable()) {
+ // Correct typos in non-C++ code earlier so that implicit-cast-like
+ // expressions are parsed correctly.
+ Result = Actions.CorrectDelayedTyposInExpr(Result);
+ }
ExprType = SimpleExpr;
if (isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis))
@@ -2354,7 +2407,8 @@ ExprResult Parser::ParseGenericSelectionExpression() {
// C11 6.5.1.1p3 "The controlling expression of a generic selection is
// not evaluated."
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
- ControllingExpr = ParseAssignmentExpression();
+ ControllingExpr =
+ Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
if (ControllingExpr.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
@@ -2400,7 +2454,8 @@ ExprResult Parser::ParseGenericSelectionExpression() {
// FIXME: These expressions should be parsed in a potentially potentially
// evaluated context.
- ExprResult ER(ParseAssignmentExpression());
+ ExprResult ER(
+ Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
if (ER.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
@@ -2493,17 +2548,14 @@ ExprResult Parser::ParseFoldExpression(ExprResult LHS,
/// [C++0x] assignment-expression
/// [C++0x] braced-init-list
/// \endverbatim
-bool Parser::ParseExpressionList(SmallVectorImpl<Expr*> &Exprs,
+bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
SmallVectorImpl<SourceLocation> &CommaLocs,
- void (Sema::*Completer)(Scope *S,
- Expr *Data,
- ArrayRef<Expr *> Args),
- Expr *Data) {
+ std::function<void()> Completer) {
bool SawError = false;
while (1) {
if (Tok.is(tok::code_completion)) {
if (Completer)
- (Actions.*Completer)(getCurScope(), Data, Exprs);
+ Completer();
else
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
cutOffParsing();
@@ -2588,9 +2640,6 @@ void Parser::ParseBlockId(SourceLocation CaretLoc) {
Declarator DeclaratorInfo(DS, Declarator::BlockLiteralContext);
ParseDeclarator(DeclaratorInfo);
- // We do this for: ^ __attribute__((noreturn)) {, as DS has the attributes.
- DeclaratorInfo.takeAttributes(DS.getAttributes(), SourceLocation());
-
MaybeParseGNUAttributes(DeclaratorInfo);
// Inform sema that we are starting a block.
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
index 67496ed..7fb4b5e 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
@@ -118,6 +118,7 @@ void Parser::CheckForLParenAfterColonColon() {
// Eat the '('.
ConsumeParen();
Token RParen;
+ RParen.setLocation(SourceLocation());
// Do we have a ')' ?
NextTok = StarTok.is(tok::star) ? GetLookAheadToken(2) : GetLookAheadToken(1);
if (NextTok.is(tok::r_paren)) {
@@ -194,6 +195,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
if (Tok.is(tok::annot_cxxscope)) {
assert(!LastII && "want last identifier but have already annotated scope");
+ assert(!MayBePseudoDestructor && "unexpected annot_cxxscope");
Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
Tok.getAnnotationRange(),
SS);
@@ -208,6 +210,13 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
SS = TemplateId->SS;
}
+ // Has to happen before any "return false"s in this function.
+ bool CheckForDestructor = false;
+ if (MayBePseudoDestructor && *MayBePseudoDestructor) {
+ CheckForDestructor = true;
+ *MayBePseudoDestructor = false;
+ }
+
if (LastII)
*LastII = nullptr;
@@ -244,14 +253,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
return Actions.ActOnSuperScopeSpecifier(SuperLoc, ConsumeToken(), SS);
}
- bool CheckForDestructor = false;
- if (MayBePseudoDestructor && *MayBePseudoDestructor) {
- CheckForDestructor = true;
- *MayBePseudoDestructor = false;
- }
-
if (!HasScopeSpecifier &&
- (Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype))) {
+ Tok.isOneOf(tok::kw_decltype, tok::annot_decltype)) {
DeclSpec DS(AttrFactory);
SourceLocation DeclLoc = Tok.getLocation();
SourceLocation EndLoc = ParseDecltypeSpecifier(DS);
@@ -484,7 +487,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// as the name in a nested-name-specifier.
Token Identifier = Tok;
SourceLocation IdLoc = ConsumeToken();
- assert((Tok.is(tok::coloncolon) || Tok.is(tok::colon)) &&
+ assert(Tok.isOneOf(tok::coloncolon, tok::colon) &&
"NextToken() not working properly!");
Token ColonColon = Tok;
SourceLocation CCLoc = ConsumeToken();
@@ -659,7 +662,8 @@ ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
Token Replacement;
- ExprResult Result = tryParseCXXIdExpression(SS, isAddressOfOperand, Replacement);
+ ExprResult Result =
+ tryParseCXXIdExpression(SS, isAddressOfOperand, Replacement);
if (Result.isUnset()) {
// If the ExprResult is valid but null, then typo correction suggested a
// keyword replacement that needs to be reparsed.
@@ -888,7 +892,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
Parens.getCloseLocation(),
Exprs);
}
- } else if (Tok.is(tok::l_brace) || Tok.is(tok::equal)) {
+ } else if (Tok.isOneOf(tok::l_brace, tok::equal)) {
// Each lambda init-capture forms its own full expression, which clears
// Actions.MaybeODRUseExprs. So create an expression evaluation context
// to save the necessary state, and restore it later.
@@ -1090,6 +1094,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
// compatible with GCC.
MaybeParseGNUAttributes(Attr, &DeclEndLoc);
+ // MSVC-style attributes must be parsed before the mutable specifier to be
+ // compatible with MSVC.
+ MaybeParseMicrosoftDeclSpecs(Attr, &DeclEndLoc);
+
// Parse 'mutable'[opt].
SourceLocation MutableLoc;
if (TryConsumeToken(tok::kw_mutable, MutableLoc))
@@ -1151,8 +1159,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
LParenLoc, FunLocalRangeEnd, D,
TrailingReturnType),
Attr, DeclEndLoc);
- } else if (Tok.is(tok::kw_mutable) || Tok.is(tok::arrow) ||
- Tok.is(tok::kw___attribute) ||
+ } else if (Tok.isOneOf(tok::kw_mutable, tok::arrow, tok::kw___attribute) ||
(Tok.is(tok::l_square) && NextToken().is(tok::l_square))) {
// It's common to forget that one needs '()' before 'mutable', an attribute
// specifier, or the result type. Deal with this.
@@ -1485,9 +1492,8 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc,
ParseDecltypeSpecifier(DS);
if (DS.getTypeSpecType() == TST_error)
return ExprError();
- return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc,
- OpKind, TildeLoc, DS,
- Tok.is(tok::l_paren));
+ return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc, OpKind,
+ TildeLoc, DS);
}
if (!Tok.is(tok::identifier)) {
@@ -1510,11 +1516,9 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc,
/*AssumeTemplateName=*/true))
return ExprError();
- return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base,
- OpLoc, OpKind,
- SS, FirstTypeName, CCLoc,
- TildeLoc, SecondTypeName,
- Tok.is(tok::l_paren));
+ return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc, OpKind,
+ SS, FirstTypeName, CCLoc, TildeLoc,
+ SecondTypeName);
}
/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
@@ -1602,7 +1606,11 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
CommaLocsTy CommaLocs;
if (Tok.isNot(tok::r_paren)) {
- if (ParseExpressionList(Exprs, CommaLocs)) {
+ if (ParseExpressionList(Exprs, CommaLocs, [&] {
+ Actions.CodeCompleteConstructor(getCurScope(),
+ TypeRep.get()->getCanonicalTypeInternal(),
+ DS.getLocEnd(), Exprs);
+ })) {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
@@ -2509,14 +2517,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
}
// If the user wrote ~T::T, correct it to T::~T.
+ DeclaratorScopeObj DeclScopeObj(*this, SS);
if (!TemplateSpecified && NextToken().is(tok::coloncolon)) {
+ // Don't let ParseOptionalCXXScopeSpecifier() "correct"
+ // `int A; struct { ~A::A(); };` to `int A; struct { ~A:A(); };`,
+ // it will confuse this recovery logic.
+ ColonProtectionRAIIObject ColonRAII(*this, false);
+
if (SS.isSet()) {
AnnotateScopeToken(SS, /*NewAnnotation*/true);
SS.clear();
}
if (ParseOptionalCXXScopeSpecifier(SS, ObjectType, EnteringContext))
return true;
- if (Tok.isNot(tok::identifier) || NextToken().is(tok::coloncolon)) {
+ if (SS.isNotEmpty())
+ ObjectType = ParsedType();
+ if (Tok.isNot(tok::identifier) || NextToken().is(tok::coloncolon) ||
+ !SS.isSet()) {
Diag(TildeLoc, diag::err_destructor_tilde_scope);
return true;
}
@@ -2525,6 +2542,10 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
Diag(TildeLoc, diag::err_destructor_tilde_scope)
<< FixItHint::CreateRemoval(TildeLoc)
<< FixItHint::CreateInsertion(Tok.getLocation(), "~");
+
+ // Temporarily enter the scope for the rest of this function.
+ if (Actions.ShouldEnterDeclaratorScope(getCurScope(), SS))
+ DeclScopeObj.EnterDeclaratorScope();
}
// Parse the class-name (or template-name in a simple-template-id).
@@ -2668,7 +2689,14 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
ConstructorLParen = T.getOpenLocation();
if (Tok.isNot(tok::r_paren)) {
CommaLocsTy CommaLocs;
- if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
+ if (ParseExpressionList(ConstructorArgs, CommaLocs, [&] {
+ ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(),
+ DeclaratorInfo).get();
+ Actions.CodeCompleteConstructor(getCurScope(),
+ TypeRep.get()->getCanonicalTypeInternal(),
+ DeclaratorInfo.getLocEnd(),
+ ConstructorArgs);
+ })) {
SkipUntil(tok::semi, StopAtSemi | StopBeforeMatch);
return ExprError();
}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp
index 7fe9862..42287d6 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp
@@ -148,7 +148,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
Diag(NameLoc, diag::ext_gnu_old_style_field_designator)
<< FixItHint::CreateReplacement(SourceRange(NameLoc, ColonLoc),
- NewSyntax.str());
+ NewSyntax);
Designation D;
D.AddDesignator(Designator::getField(FieldName, SourceLocation(), NameLoc));
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp
index a597a16..e4f7911 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp
@@ -13,6 +13,7 @@
#include "clang/Parse/Parser.h"
#include "RAIIObjectsForParser.h"
+#include "clang/AST/ASTContext.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
@@ -240,7 +241,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
SmallVector<Decl *, 8> ProtocolRefs;
SmallVector<SourceLocation, 8> ProtocolLocs;
if (Tok.is(tok::less) &&
- ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
+ ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, true,
LAngleLoc, EndProtoLoc))
return nullptr;
@@ -286,7 +287,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
SmallVector<SourceLocation, 8> ProtocolLocs;
SourceLocation LAngleLoc, EndProtoLoc;
if (Tok.is(tok::less) &&
- ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
+ ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, true,
LAngleLoc, EndProtoLoc))
return nullptr;
@@ -307,6 +308,37 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
return ClsType;
}
+/// Add an attribute for a context-sensitive type nullability to the given
+/// declarator.
+static void addContextSensitiveTypeNullability(Parser &P,
+ Declarator &D,
+ NullabilityKind nullability,
+ SourceLocation nullabilityLoc,
+ bool &addedToDeclSpec) {
+ // Create the attribute.
+ auto getNullabilityAttr = [&]() -> AttributeList * {
+ return D.getAttributePool().create(
+ P.getNullabilityKeyword(nullability),
+ SourceRange(nullabilityLoc),
+ nullptr, SourceLocation(),
+ nullptr, 0,
+ AttributeList::AS_ContextSensitiveKeyword);
+ };
+
+ if (D.getNumTypeObjects() > 0) {
+ // Add the attribute to the declarator chunk nearest the declarator.
+ auto nullabilityAttr = getNullabilityAttr();
+ DeclaratorChunk &chunk = D.getTypeObject(0);
+ nullabilityAttr->setNext(chunk.getAttrListRef());
+ chunk.getAttrListRef() = nullabilityAttr;
+ } else if (!addedToDeclSpec) {
+ // Otherwise, just put it on the declaration specifiers (if one
+ // isn't there already).
+ D.getMutableDeclSpec().addAttributes(getNullabilityAttr());
+ addedToDeclSpec = true;
+ }
+}
+
/// objc-interface-decl-list:
/// empty
/// objc-interface-decl-list objc-property-decl [OBJC2]
@@ -330,7 +362,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
while (1) {
// If this is a method prototype, parse it.
- if (Tok.is(tok::minus) || Tok.is(tok::plus)) {
+ if (Tok.isOneOf(tok::minus, tok::plus)) {
if (Decl *methodPrototype =
ParseObjCMethodPrototype(MethodImplKind, false))
allMethods.push_back(methodPrototype);
@@ -445,6 +477,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
ParseObjCPropertyAttribute(OCDS);
}
+ bool addedToDeclSpec = false;
auto ObjCPropertyCallback = [&](ParsingFieldDeclarator &FD) {
if (FD.D.getIdentifier() == nullptr) {
Diag(AtLoc, diag::err_objc_property_requires_field_name)
@@ -457,6 +490,13 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
return;
}
+ // Map a nullability property attribute to a context-sensitive keyword
+ // attribute.
+ if (OCDS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)
+ addContextSensitiveTypeNullability(*this, FD.D, OCDS.getNullability(),
+ OCDS.getNullabilityLoc(),
+ addedToDeclSpec);
+
// Install the property declarator into interfaceDecl.
IdentifierInfo *SelName =
OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();
@@ -510,6 +550,24 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
Actions.ActOnAtEnd(getCurScope(), AtEnd, allMethods, allTUVariables);
}
+/// Diagnose redundant or conflicting nullability information.
+static void diagnoseRedundantPropertyNullability(Parser &P,
+ ObjCDeclSpec &DS,
+ NullabilityKind nullability,
+ SourceLocation nullabilityLoc){
+ if (DS.getNullability() == nullability) {
+ P.Diag(nullabilityLoc, diag::warn_nullability_duplicate)
+ << static_cast<unsigned>(nullability) << true
+ << SourceRange(DS.getNullabilityLoc());
+ return;
+ }
+
+ P.Diag(nullabilityLoc, diag::err_nullability_conflicting)
+ << static_cast<unsigned>(nullability) << true
+ << static_cast<unsigned>(DS.getNullability()) << true
+ << SourceRange(DS.getNullabilityLoc());
+}
+
/// Parse property attribute declarations.
///
/// property-attr-decl: '(' property-attrlist ')'
@@ -529,6 +587,10 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
/// strong
/// weak
/// unsafe_unretained
+/// nonnull
+/// nullable
+/// null_unspecified
+/// null_resettable
///
void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
assert(Tok.getKind() == tok::l_paren);
@@ -614,6 +676,37 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter);
DS.setGetterName(SelIdent);
}
+ } else if (II->isStr("nonnull")) {
+ if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)
+ diagnoseRedundantPropertyNullability(*this, DS,
+ NullabilityKind::NonNull,
+ Tok.getLocation());
+ DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability);
+ DS.setNullability(Tok.getLocation(), NullabilityKind::NonNull);
+ } else if (II->isStr("nullable")) {
+ if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)
+ diagnoseRedundantPropertyNullability(*this, DS,
+ NullabilityKind::Nullable,
+ Tok.getLocation());
+ DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability);
+ DS.setNullability(Tok.getLocation(), NullabilityKind::Nullable);
+ } else if (II->isStr("null_unspecified")) {
+ if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)
+ diagnoseRedundantPropertyNullability(*this, DS,
+ NullabilityKind::Unspecified,
+ Tok.getLocation());
+ DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability);
+ DS.setNullability(Tok.getLocation(), NullabilityKind::Unspecified);
+ } else if (II->isStr("null_resettable")) {
+ if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)
+ diagnoseRedundantPropertyNullability(*this, DS,
+ NullabilityKind::Unspecified,
+ Tok.getLocation());
+ DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability);
+ DS.setNullability(Tok.getLocation(), NullabilityKind::Unspecified);
+
+ // Also set the null_resettable bit.
+ DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_null_resettable);
} else {
Diag(AttrName, diag::err_objc_expected_property_attr) << II;
SkipUntil(tok::r_paren, StopAtSemi);
@@ -641,7 +734,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
///
Decl *Parser::ParseObjCMethodPrototype(tok::ObjCKeywordKind MethodImplKind,
bool MethodDefinition) {
- assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-");
+ assert(Tok.isOneOf(tok::minus, tok::plus) && "expected +/-");
tok::TokenKind methodType = Tok.getKind();
SourceLocation mLoc = ConsumeToken();
@@ -779,6 +872,17 @@ bool Parser::isTokIdentifier_in() const {
/// objc-type-qualifier
/// objc-type-qualifiers objc-type-qualifier
///
+/// objc-type-qualifier:
+/// 'in'
+/// 'out'
+/// 'inout'
+/// 'oneway'
+/// 'bycopy'
+/// 'byref'
+/// 'nonnull'
+/// 'nullable'
+/// 'null_unspecified'
+///
void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
Declarator::TheContext Context) {
assert(Context == Declarator::ObjCParameterContext ||
@@ -796,10 +900,13 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
const IdentifierInfo *II = Tok.getIdentifierInfo();
for (unsigned i = 0; i != objc_NumQuals; ++i) {
- if (II != ObjCTypeQuals[i])
+ if (II != ObjCTypeQuals[i] ||
+ NextToken().is(tok::less) ||
+ NextToken().is(tok::coloncolon))
continue;
ObjCDeclSpec::ObjCDeclQualifier Qual;
+ NullabilityKind Nullability;
switch (i) {
default: llvm_unreachable("Unknown decl qualifier");
case objc_in: Qual = ObjCDeclSpec::DQ_In; break;
@@ -808,8 +915,28 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
case objc_oneway: Qual = ObjCDeclSpec::DQ_Oneway; break;
case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break;
case objc_byref: Qual = ObjCDeclSpec::DQ_Byref; break;
+
+ case objc_nonnull:
+ Qual = ObjCDeclSpec::DQ_CSNullability;
+ Nullability = NullabilityKind::NonNull;
+ break;
+
+ case objc_nullable:
+ Qual = ObjCDeclSpec::DQ_CSNullability;
+ Nullability = NullabilityKind::Nullable;
+ break;
+
+ case objc_null_unspecified:
+ Qual = ObjCDeclSpec::DQ_CSNullability;
+ Nullability = NullabilityKind::Unspecified;
+ break;
}
+
+ // FIXME: Diagnose redundant specifiers.
DS.setObjCDeclQualifier(Qual);
+ if (Qual == ObjCDeclSpec::DQ_CSNullability)
+ DS.setNullability(Tok.getLocation(), Nullability);
+
ConsumeToken();
II = nullptr;
break;
@@ -878,17 +1005,28 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
ParseObjCTypeQualifierList(DS, context);
ParsedType Ty;
- if (isTypeSpecifierQualifier()) {
+ if (isTypeSpecifierQualifier() || isObjCInstancetype()) {
// Parse an abstract declarator.
DeclSpec declSpec(AttrFactory);
declSpec.setObjCQualifiers(&DS);
- ParseSpecifierQualifierList(declSpec);
+ DeclSpecContext dsContext = DSC_normal;
+ if (context == Declarator::ObjCResultContext)
+ dsContext = DSC_objc_method_result;
+ ParseSpecifierQualifierList(declSpec, AS_none, dsContext);
declSpec.SetRangeEnd(Tok.getLocation());
Declarator declarator(declSpec, context);
ParseDeclarator(declarator);
// If that's not invalid, extract a type.
if (!declarator.isInvalidType()) {
+ // Map a nullability specifier to a context-sensitive keyword attribute.
+ bool addedToDeclSpec = false;
+ if (DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability)
+ addContextSensitiveTypeNullability(*this, declarator,
+ DS.getNullability(),
+ DS.getNullabilityLoc(),
+ addedToDeclSpec);
+
TypeResult type = Actions.ActOnTypeName(getCurScope(), declarator);
if (!type.isInvalid())
Ty = type.get();
@@ -898,15 +1036,6 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
if (context == Declarator::ObjCParameterContext)
takeDeclAttributes(*paramAttrs, declarator);
}
- } else if (context == Declarator::ObjCResultContext &&
- Tok.is(tok::identifier)) {
- if (!Ident_instancetype)
- Ident_instancetype = PP.getIdentifierInfo("instancetype");
-
- if (Tok.getIdentifierInfo() == Ident_instancetype) {
- Ty = Actions.ActOnObjCInstanceType(Tok.getLocation());
- ConsumeToken();
- }
}
if (Tok.is(tok::r_paren))
@@ -1151,7 +1280,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
bool Parser::
ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,
SmallVectorImpl<SourceLocation> &ProtocolLocs,
- bool WarnOnDeclarations,
+ bool WarnOnDeclarations, bool ForObjCContainer,
SourceLocation &LAngleLoc, SourceLocation &EndLoc) {
assert(Tok.is(tok::less) && "expected <");
@@ -1186,7 +1315,7 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,
return true;
// Convert the list of protocols identifiers into a list of protocol decls.
- Actions.FindProtocolDeclaration(WarnOnDeclarations,
+ Actions.FindProtocolDeclaration(WarnOnDeclarations, ForObjCContainer,
&ProtocolIdents[0], ProtocolIdents.size(),
Protocols);
return false;
@@ -1201,6 +1330,7 @@ bool Parser::ParseObjCProtocolQualifiers(DeclSpec &DS) {
SmallVector<Decl *, 8> ProtocolDecl;
SmallVector<SourceLocation, 8> ProtocolLocs;
bool Result = ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
+ false,
LAngleLoc, EndProtoLoc);
DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
ProtocolLocs.data(), LAngleLoc);
@@ -1308,6 +1438,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
auto ObjCIvarCallback = [&](ParsingFieldDeclarator &FD) {
Actions.ActOnObjCContainerStartDefinition(interfaceDecl);
// Install the declarator into the interface decl.
+ FD.D.setObjCIvar(true);
Decl *Field = Actions.ActOnIvar(
getCurScope(), FD.D.getDeclSpec().getSourceRange().getBegin(), FD.D,
FD.BitfieldSize, visibility);
@@ -1416,7 +1547,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
SmallVector<Decl *, 8> ProtocolRefs;
SmallVector<SourceLocation, 8> ProtocolLocs;
if (Tok.is(tok::less) &&
- ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false,
+ ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false, true,
LAngleLoc, EndProtoLoc))
return DeclGroupPtrTy();
@@ -2169,8 +2300,8 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
InMessageExpressionRAIIObject InMessage(*this, true);
- if (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
- Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope))
+ if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_typename,
+ tok::annot_cxxscope))
TryAnnotateTypeOrScopeToken();
if (!Actions.isSimpleTypeSpecifier(Tok.getKind())) {
@@ -2264,7 +2395,7 @@ bool Parser::isStartOfObjCClassMessageMissingOpenBracket() {
if (!Type.get().isNull() && Type.get()->isObjCObjectOrInterfaceType()) {
const Token &AfterNext = GetLookAheadToken(2);
- if (AfterNext.is(tok::colon) || AfterNext.is(tok::r_square)) {
+ if (AfterNext.isOneOf(tok::colon, tok::r_square)) {
if (Tok.is(tok::identifier))
TryAnnotateTypeOrScopeToken();
@@ -2890,9 +3021,8 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
// Consume the previously pushed token.
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
- assert((Tok.is(tok::l_brace) || Tok.is(tok::kw_try) ||
- Tok.is(tok::colon)) &&
- "Inline objective-c method not starting with '{' or 'try' or ':'");
+ assert(Tok.isOneOf(tok::l_brace, tok::kw_try, tok::colon) &&
+ "Inline objective-c method not starting with '{' or 'try' or ':'");
// Enter a scope for the method or c-function body.
ParseScope BodyScope(this,
parseMethod
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
index 764619a..a3c3c5d 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
@@ -94,6 +94,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:
+ case OMPD_taskgroup:
case OMPD_flush:
case OMPD_for:
case OMPD_for_simd:
@@ -128,7 +129,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
/// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
/// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
/// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
-/// 'for simd' | 'parallel for simd' | 'target' | 'teams' {clause}
+/// 'for simd' | 'parallel for simd' | 'target' | 'teams' | 'taskgroup'
+/// {clause}
/// annot_pragma_openmp_end
///
StmtResult
@@ -198,7 +200,8 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
case OMPD_ordered:
case OMPD_atomic:
case OMPD_target:
- case OMPD_teams: {
+ case OMPD_teams:
+ case OMPD_taskgroup: {
ConsumeToken();
// Parse directive name of the 'critical' directive if any.
if (DKind == OMPD_critical) {
@@ -223,6 +226,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
ParseScope OMPDirectiveScope(this, ScopeFlags);
Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
+ Actions.StartOpenMPClauses();
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
OpenMPClauseKind CKind =
Tok.isAnnotation()
@@ -242,6 +246,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
if (Tok.is(tok::comma))
ConsumeToken();
}
+ Actions.EndOpenMPClauses();
// End location of the directive.
EndLoc = Tok.getLocation();
// Consume final annot_pragma_openmp_end.
@@ -257,13 +262,8 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
// Parse statement
AssociatedStmt = ParseStatement();
Actions.ActOnFinishOfCompoundStmt();
- if (!AssociatedStmt.isUsable()) {
- Actions.ActOnCapturedRegionError();
- CreateDirective = false;
- } else {
- AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.get());
- CreateDirective = AssociatedStmt.isUsable();
- }
+ AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
+ CreateDirective = AssociatedStmt.isUsable();
}
if (CreateDirective)
Directive = Actions.ActOnOpenMPExecutableDirective(
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
index 473be54..892d3c6 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
@@ -198,9 +198,12 @@ void Parser::initializePragmaHandlers() {
OpenMPHandler.reset(new PragmaNoOpenMPHandler());
PP.AddPragmaHandler(OpenMPHandler.get());
- if (getLangOpts().MicrosoftExt) {
+ if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
MSCommentHandler.reset(new PragmaCommentHandler(Actions));
PP.AddPragmaHandler(MSCommentHandler.get());
+ }
+
+ if (getLangOpts().MicrosoftExt) {
MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
PP.AddPragmaHandler(MSDetectMismatchHandler.get());
MSPointersToMembers.reset(new PragmaMSPointersToMembers());
@@ -261,9 +264,12 @@ void Parser::resetPragmaHandlers() {
PP.RemovePragmaHandler(OpenMPHandler.get());
OpenMPHandler.reset();
- if (getLangOpts().MicrosoftExt) {
+ if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
PP.RemovePragmaHandler(MSCommentHandler.get());
MSCommentHandler.reset();
+ }
+
+ if (getLangOpts().MicrosoftExt) {
PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
MSDetectMismatchHandler.reset();
PP.RemovePragmaHandler(MSPointersToMembers.get());
@@ -793,8 +799,10 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
"PragmaLoopHintInfo::Toks must contain at least one token.");
// If no option is specified the argument is assumed to be a constant expr.
+ bool OptionUnroll = false;
bool StateOption = false;
- if (OptionInfo) { // Pragma unroll does not specify an option.
+ if (OptionInfo) { // Pragma Unroll does not specify an option.
+ OptionUnroll = OptionInfo->isStr("unroll");
StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
.Case("vectorize", true)
.Case("interleave", true)
@@ -806,19 +814,20 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
if (Toks[0].is(tok::eof)) {
ConsumeToken(); // The annotation token.
Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
- << /*StateArgument=*/StateOption << /*FullKeyword=*/PragmaUnroll;
+ << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll;
return false;
}
// Validate the argument.
if (StateOption) {
ConsumeToken(); // The annotation token.
- bool OptionUnroll = OptionInfo->isStr("unroll");
SourceLocation StateLoc = Toks[0].getLocation();
IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
- if (!StateInfo || ((OptionUnroll ? !StateInfo->isStr("full")
- : !StateInfo->isStr("enable")) &&
- !StateInfo->isStr("disable"))) {
+ if (!StateInfo ||
+ ((OptionUnroll ? !StateInfo->isStr("full")
+ : !StateInfo->isStr("enable") &&
+ !StateInfo->isStr("assume_safety")) &&
+ !StateInfo->isStr("disable"))) {
Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
<< /*FullKeyword=*/OptionUnroll;
return false;
@@ -900,6 +909,7 @@ void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
<< "visibility";
return;
}
+ SourceLocation EndLoc = Tok.getLocation();
PP.LexUnexpandedToken(Tok);
if (Tok.isNot(tok::eod)) {
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
@@ -911,6 +921,7 @@ void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
Toks[0].startToken();
Toks[0].setKind(tok::annot_pragma_vis);
Toks[0].setLocation(VisLoc);
+ Toks[0].setAnnotationEndLoc(EndLoc);
Toks[0].setAnnotationValue(
const_cast<void*>(static_cast<const void*>(VisType)));
PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
@@ -1030,6 +1041,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP,
Toks[0].startToken();
Toks[0].setKind(tok::annot_pragma_pack);
Toks[0].setLocation(PackLoc);
+ Toks[0].setAnnotationEndLoc(RParenLoc);
Toks[0].setAnnotationValue(static_cast<void*>(Info));
PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
/*OwnsTokens=*/false);
@@ -1048,6 +1060,7 @@ void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
return;
}
+ SourceLocation EndLoc = Tok.getLocation();
const IdentifierInfo *II = Tok.getIdentifierInfo();
if (II->isStr("on")) {
Kind = Sema::PMSST_ON;
@@ -1073,6 +1086,7 @@ void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
Toks[0].startToken();
Toks[0].setKind(tok::annot_pragma_msstruct);
Toks[0].setLocation(MSStructTok.getLocation());
+ Toks[0].setAnnotationEndLoc(EndLoc);
Toks[0].setAnnotationValue(reinterpret_cast<void*>(
static_cast<uintptr_t>(Kind)));
PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
@@ -1128,6 +1142,7 @@ static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
return;
}
+ SourceLocation EndLoc = Tok.getLocation();
PP.Lex(Tok);
if (Tok.isNot(tok::eod)) {
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
@@ -1142,6 +1157,7 @@ static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Toks[0].startToken();
Toks[0].setKind(tok::annot_pragma_align);
Toks[0].setLocation(FirstTok.getLocation());
+ Toks[0].setAnnotationEndLoc(EndLoc);
Toks[0].setAnnotationValue(reinterpret_cast<void*>(
static_cast<uintptr_t>(Kind)));
PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
@@ -1285,6 +1301,7 @@ void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
pragmaUnusedTok.startToken();
pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
pragmaUnusedTok.setLocation(WeakLoc);
+ pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
Toks[1] = WeakName;
Toks[2] = AliasName;
PP.EnterTokenStream(Toks, 3,
@@ -1297,6 +1314,7 @@ void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
pragmaUnusedTok.startToken();
pragmaUnusedTok.setKind(tok::annot_pragma_weak);
pragmaUnusedTok.setLocation(WeakLoc);
+ pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
Toks[1] = WeakName;
PP.EnterTokenStream(Toks, 2,
/*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
@@ -1342,6 +1360,7 @@ void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
pragmaRedefTok.startToken();
pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
pragmaRedefTok.setLocation(RedefLoc);
+ pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
Toks[1] = RedefName;
Toks[2] = AliasName;
PP.EnterTokenStream(Toks, 3,
@@ -1364,6 +1383,7 @@ PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
Toks[0].startToken();
Toks[0].setKind(tok::annot_pragma_fp_contract);
Toks[0].setLocation(Tok.getLocation());
+ Toks[0].setAnnotationEndLoc(Tok.getLocation());
Toks[0].setAnnotationValue(reinterpret_cast<void*>(
static_cast<uintptr_t>(OOS)));
PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
@@ -1423,6 +1443,7 @@ PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
Toks[0].setKind(tok::annot_pragma_opencl_extension);
Toks[0].setLocation(NameLoc);
Toks[0].setAnnotationValue(data.getOpaqueValue());
+ Toks[0].setAnnotationEndLoc(StateLoc);
PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
/*OwnsTokens=*/false);
@@ -1471,7 +1492,7 @@ PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
Token *Toks = new Token[Pragma.size()];
std::copy(Pragma.begin(), Pragma.end(), Toks);
PP.EnterTokenStream(Toks, Pragma.size(),
- /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
+ /*DisableMacroExpansion=*/false, /*OwnsTokens=*/true);
}
/// \brief Handle '#pragma pointers_to_members'
@@ -1554,6 +1575,7 @@ void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
return;
}
+ SourceLocation EndLoc = Tok.getLocation();
PP.Lex(Tok);
if (Tok.isNot(tok::eod)) {
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
@@ -1565,6 +1587,7 @@ void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
AnnotTok.startToken();
AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
AnnotTok.setLocation(PointersToMembersLoc);
+ AnnotTok.setAnnotationEndLoc(EndLoc);
AnnotTok.setAnnotationValue(
reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
PP.EnterToken(AnnotTok);
@@ -1644,6 +1667,7 @@ void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
return;
}
+ SourceLocation EndLoc = Tok.getLocation();
PP.Lex(Tok);
if (Tok.isNot(tok::eod)) {
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
@@ -1656,6 +1680,7 @@ void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
AnnotTok.startToken();
AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
AnnotTok.setLocation(VtorDispLoc);
+ AnnotTok.setAnnotationEndLoc(EndLoc);
AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF))));
PP.EnterToken(AnnotTok);
@@ -1672,10 +1697,13 @@ void PragmaMSPragma::HandlePragma(Preprocessor &PP,
AnnotTok.startToken();
AnnotTok.setKind(tok::annot_pragma_ms_pragma);
AnnotTok.setLocation(Tok.getLocation());
+ AnnotTok.setAnnotationEndLoc(Tok.getLocation());
SmallVector<Token, 8> TokenVector;
// Suck up all of the tokens before the eod.
- for (; Tok.isNot(tok::eod); PP.Lex(Tok))
+ for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
TokenVector.push_back(Tok);
+ AnnotTok.setAnnotationEndLoc(Tok.getLocation());
+ }
// Add a sentinal EoF token to the end of the list.
TokenVector.push_back(EoF);
// We must allocate this array with new because EnterTokenStream is going to
@@ -1786,6 +1814,14 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
return;
}
+ // On PS4, issue a warning about any pragma comments other than
+ // #pragma comment lib.
+ if (PP.getTargetInfo().getTriple().isPS4() && Kind != Sema::PCK_Lib) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
+ << II->getName();
+ return;
+ }
+
// Read the optional string if present.
PP.Lex(Tok);
std::string ArgumentString;
@@ -1920,6 +1956,7 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
/// loop-hint-keyword:
/// 'enable'
/// 'disable'
+/// 'assume_safety'
///
/// unroll-hint-keyword:
/// 'full'
@@ -1994,6 +2031,7 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
LoopHintTok.startToken();
LoopHintTok.setKind(tok::annot_pragma_loop_hint);
LoopHintTok.setLocation(PragmaName.getLocation());
+ LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
TokenList.push_back(LoopHintTok);
}
@@ -2076,6 +2114,7 @@ void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
TokenArray[0].startToken();
TokenArray[0].setKind(tok::annot_pragma_loop_hint);
TokenArray[0].setLocation(PragmaName.getLocation());
+ TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
PP.EnterTokenStream(TokenArray, 1, /*DisableMacroExpansion=*/false,
/*OwnsTokens=*/true);
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp
index 2a5f840..b658cef 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp
@@ -119,15 +119,12 @@ namespace {
class StatementFilterCCC : public CorrectionCandidateCallback {
public:
StatementFilterCCC(Token nextTok) : NextToken(nextTok) {
- WantTypeSpecifiers = nextTok.is(tok::l_paren) || nextTok.is(tok::less) ||
- nextTok.is(tok::identifier) || nextTok.is(tok::star) ||
- nextTok.is(tok::amp) || nextTok.is(tok::l_square);
- WantExpressionKeywords = nextTok.is(tok::l_paren) ||
- nextTok.is(tok::identifier) ||
- nextTok.is(tok::arrow) || nextTok.is(tok::period);
- WantRemainingKeywords = nextTok.is(tok::l_paren) || nextTok.is(tok::semi) ||
- nextTok.is(tok::identifier) ||
- nextTok.is(tok::l_brace);
+ WantTypeSpecifiers = nextTok.isOneOf(tok::l_paren, tok::less, tok::l_square,
+ tok::identifier, tok::star, tok::amp);
+ WantExpressionKeywords =
+ nextTok.isOneOf(tok::l_paren, tok::identifier, tok::arrow, tok::period);
+ WantRemainingKeywords =
+ nextTok.isOneOf(tok::l_paren, tok::semi, tok::identifier, tok::l_brace);
WantCXXNamedCasts = false;
}
@@ -408,12 +405,6 @@ StmtResult Parser::ParseExprStatement() {
return Actions.ActOnExprStmt(Expr);
}
-StmtResult Parser::ParseSEHTryBlock() {
- assert(Tok.is(tok::kw___try) && "Expected '__try'");
- SourceLocation Loc = ConsumeToken();
- return ParseSEHTryBlockCommon(Loc);
-}
-
/// ParseSEHTryBlockCommon
///
/// seh-try-block:
@@ -423,8 +414,11 @@ StmtResult Parser::ParseSEHTryBlock() {
/// seh-except-block
/// seh-finally-block
///
-StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) {
- if(Tok.isNot(tok::l_brace))
+StmtResult Parser::ParseSEHTryBlock() {
+ assert(Tok.is(tok::kw___try) && "Expected '__try'");
+ SourceLocation TryLoc = ConsumeToken();
+
+ if (Tok.isNot(tok::l_brace))
return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false,
@@ -441,7 +435,7 @@ StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) {
SourceLocation Loc = ConsumeToken();
Handler = ParseSEHFinallyBlock(Loc);
} else {
- return StmtError(Diag(Tok,diag::err_seh_expected_handler));
+ return StmtError(Diag(Tok, diag::err_seh_expected_handler));
}
if(Handler.isInvalid())
@@ -466,14 +460,21 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) {
if (ExpectAndConsume(tok::l_paren))
return StmtError();
- ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope);
+ ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope |
+ Scope::SEHExceptScope);
if (getLangOpts().Borland) {
Ident__exception_info->setIsPoisoned(false);
Ident___exception_info->setIsPoisoned(false);
Ident_GetExceptionInfo->setIsPoisoned(false);
}
- ExprResult FilterExpr(ParseExpression());
+
+ ExprResult FilterExpr;
+ {
+ ParseScopeFlags FilterScope(this, getCurScope()->getFlags() |
+ Scope::SEHFilterScope);
+ FilterExpr = Actions.CorrectDelayedTyposInExpr(ParseExpression());
+ }
if (getLangOpts().Borland) {
Ident__exception_info->setIsPoisoned(true);
@@ -487,6 +488,9 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) {
if (ExpectAndConsume(tok::r_paren))
return StmtError();
+ if (Tok.isNot(tok::l_brace))
+ return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
+
StmtResult Block(ParseCompoundStatement());
if(Block.isInvalid())
@@ -500,16 +504,24 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) {
/// seh-finally-block:
/// '__finally' compound-statement
///
-StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyBlock) {
+StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyLoc) {
PoisonIdentifierRAIIObject raii(Ident__abnormal_termination, false),
raii2(Ident___abnormal_termination, false),
raii3(Ident_AbnormalTermination, false);
+ if (Tok.isNot(tok::l_brace))
+ return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
+
+ ParseScope FinallyScope(this, 0);
+ Actions.ActOnStartSEHFinallyBlock();
+
StmtResult Block(ParseCompoundStatement());
- if(Block.isInvalid())
+ if(Block.isInvalid()) {
+ Actions.ActOnAbortSEHFinallyBlock();
return Block;
+ }
- return Actions.ActOnSEHFinallyBlock(FinallyBlock,Block.get());
+ return Actions.ActOnFinishSEHFinallyBlock(FinallyLoc, Block.get());
}
/// Handle __leave
@@ -1253,7 +1265,7 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) {
// We have incremented the mangling number for the SwitchScope and the
// InnerScope, which is one too many.
if (C99orCXX)
- getCurScope()->decrementMSLocalManglingNumber();
+ getCurScope()->decrementMSManglingNumber();
// Read the body statement.
StmtResult Body(ParseStatement(TrailingElseLoc));
@@ -1412,7 +1424,7 @@ bool Parser::isForRangeIdentifier() {
if (Next.is(tok::colon))
return true;
- if (Next.is(tok::l_square) || Next.is(tok::kw_alignas)) {
+ if (Next.isOneOf(tok::l_square, tok::kw_alignas)) {
TentativeParsingAction PA(*this);
ConsumeToken();
SkipCXX11Attributes();
@@ -1674,6 +1686,12 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
FirstPart.get(),
Collection.get(),
T.getCloseLocation());
+ } else {
+ // In OpenMP loop region loop control variable must be captured and be
+ // private. Perform analysis of first part (if any).
+ if (getLangOpts().OpenMP && FirstPart.isUsable()) {
+ Actions.ActOnOpenMPLoopInitialization(ForLoc, FirstPart.get());
+ }
}
// C99 6.8.5p5 - In C99, the body of the for statement is a scope, even if
@@ -1695,7 +1713,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
// It will only be incremented if the body contains other things that would
// normally increment the mangling number (like a compound statement).
if (C99orCXXorObjC)
- getCurScope()->decrementMSLocalManglingNumber();
+ getCurScope()->decrementMSManglingNumber();
// Read the body statement.
StmtResult Body(ParseStatement(TrailingElseLoc));
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp
index 7bf4da6..8cdae6a 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp
@@ -512,8 +512,8 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
llvm::SourceMgr TempSrcMgr;
llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr);
- MOFI->InitMCObjectFileInfo(TT, llvm::Reloc::Default, llvm::CodeModel::Default,
- Ctx);
+ MOFI->InitMCObjectFileInfo(TheTriple, llvm::Reloc::Default,
+ llvm::CodeModel::Default, Ctx);
std::unique_ptr<llvm::MemoryBuffer> Buffer =
llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS inline asm>");
@@ -530,7 +530,7 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
TheTarget->createMCAsmParser(*STI, *Parser, *MII, MCOptions));
std::unique_ptr<llvm::MCInstPrinter> IP(
- TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI));
+ TheTarget->createMCInstPrinter(llvm::Triple(TT), 1, *MAI, *MII, *MRI));
// Change to the Intel dialect.
Parser->setAssemblerDialect(1);
@@ -615,6 +615,7 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) {
msAsm = true;
return ParseMicrosoftAsmStatement(AsmLoc);
}
+
DeclSpec DS(AttrFactory);
SourceLocation Loc = Tok.getLocation();
ParseTypeQualifierListOpt(DS, AR_VendorAttributesParsed);
@@ -639,6 +640,15 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) {
T.consumeOpen();
ExprResult AsmString(ParseAsmStringLiteral());
+
+ // Check if GNU-style InlineAsm is disabled.
+ // Error on anything other than empty string.
+ if (!(getLangOpts().GNUAsm || AsmString.isInvalid())) {
+ const auto *SL = cast<StringLiteral>(AsmString.get());
+ if (!SL->getString().trim().empty())
+ Diag(Loc, diag::err_gnu_inline_asm_disabled);
+ }
+
if (AsmString.isInvalid()) {
// Consume up to and including the closing paren.
T.skipToEnd();
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
index 53de72c..a811678 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
@@ -14,6 +14,7 @@
#include "clang/Parse/Parser.h"
#include "RAIIObjectsForParser.h"
#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
@@ -61,7 +62,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
SourceLocation &DeclEnd,
AccessSpecifier AS,
AttributeList *AccessAttrs) {
- assert((Tok.is(tok::kw_export) || Tok.is(tok::kw_template)) &&
+ assert(Tok.isOneOf(tok::kw_export, tok::kw_template) &&
"Token does not start a template declaration.");
// Enter template-parameter scope.
@@ -134,7 +135,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
} else {
LastParamListWasEmpty = true;
}
- } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
+ } while (Tok.isOneOf(tok::kw_export, tok::kw_template));
// Parse the actual template declaration.
return ParseSingleDeclarationAfterTemplate(Context,
@@ -366,7 +367,7 @@ Parser::ParseTemplateParameterList(unsigned Depth,
// Did we find a comma or the end of the template parameter list?
if (Tok.is(tok::comma)) {
ConsumeToken();
- } else if (Tok.is(tok::greater) || Tok.is(tok::greatergreater)) {
+ } else if (Tok.isOneOf(tok::greater, tok::greatergreater)) {
// Don't consume this... that's done by template parser.
break;
} else {
@@ -483,7 +484,7 @@ Decl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
/// 'typename' ...[opt][C++0x] identifier[opt]
/// 'typename' identifier[opt] '=' type-id
Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
- assert((Tok.is(tok::kw_class) || Tok.is(tok::kw_typename)) &&
+ assert(Tok.isOneOf(tok::kw_class, tok::kw_typename) &&
"A type-parameter starts with 'class' or 'typename'");
// Consume the 'class' or 'typename' keyword.
@@ -505,8 +506,8 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
if (Tok.is(tok::identifier)) {
ParamName = Tok.getIdentifierInfo();
NameLoc = ConsumeToken();
- } else if (Tok.is(tok::equal) || Tok.is(tok::comma) ||
- Tok.is(tok::greater) || Tok.is(tok::greatergreater)) {
+ } else if (Tok.isOneOf(tok::equal, tok::comma, tok::greater,
+ tok::greatergreater)) {
// Unnamed template parameter. Don't have to do anything here, just
// don't consume this token.
} else {
@@ -566,7 +567,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
// or greater appear immediately or after 'struct'. In the latter case,
// replace the keyword with 'class'.
if (!TryConsumeToken(tok::kw_class)) {
- bool Replace = Tok.is(tok::kw_typename) || Tok.is(tok::kw_struct);
+ bool Replace = Tok.isOneOf(tok::kw_typename, tok::kw_struct);
const Token &Next = Tok.is(tok::kw_struct) ? NextToken() : Tok;
if (Tok.is(tok::kw_typename)) {
Diag(Tok.getLocation(),
@@ -576,9 +577,8 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
<< (!getLangOpts().CPlusPlus1z
? FixItHint::CreateReplacement(Tok.getLocation(), "class")
: FixItHint());
- } else if (Next.is(tok::identifier) || Next.is(tok::comma) ||
- Next.is(tok::greater) || Next.is(tok::greatergreater) ||
- Next.is(tok::ellipsis)) {
+ } else if (Next.isOneOf(tok::identifier, tok::comma, tok::greater,
+ tok::greatergreater, tok::ellipsis)) {
Diag(Tok.getLocation(), diag::err_class_on_template_template_param)
<< (Replace ? FixItHint::CreateReplacement(Tok.getLocation(), "class")
: FixItHint::CreateInsertion(Tok.getLocation(), "class "));
@@ -603,8 +603,8 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
if (Tok.is(tok::identifier)) {
ParamName = Tok.getIdentifierInfo();
NameLoc = ConsumeToken();
- } else if (Tok.is(tok::equal) || Tok.is(tok::comma) ||
- Tok.is(tok::greater) || Tok.is(tok::greatergreater)) {
+ } else if (Tok.isOneOf(tok::equal, tok::comma, tok::greater,
+ tok::greatergreater)) {
// Unnamed template parameter. Don't have to do anything here, just
// don't consume this token.
} else {
@@ -793,16 +793,15 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
Token Next = NextToken();
if ((RemainingToken == tok::greater ||
RemainingToken == tok::greatergreater) &&
- (Next.is(tok::greater) || Next.is(tok::greatergreater) ||
- Next.is(tok::greatergreatergreater) || Next.is(tok::equal) ||
- Next.is(tok::greaterequal) || Next.is(tok::greatergreaterequal) ||
- Next.is(tok::equalequal)) &&
+ Next.isOneOf(tok::greater, tok::greatergreater,
+ tok::greatergreatergreater, tok::equal, tok::greaterequal,
+ tok::greatergreaterequal, tok::equalequal) &&
areTokensAdjacent(Tok, Next))
Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " ");
unsigned DiagId = diag::err_two_right_angle_brackets_need_space;
if (getLangOpts().CPlusPlus11 &&
- (Tok.is(tok::greatergreater) || Tok.is(tok::greatergreatergreater)))
+ Tok.isOneOf(tok::greatergreater, tok::greatergreatergreater))
DiagId = diag::warn_cxx98_compat_two_right_angle_brackets;
else if (Tok.is(tok::greaterequal))
DiagId = diag::err_right_angle_bracket_equal_needs_space;
@@ -1054,8 +1053,7 @@ void Parser::AnnotateTemplateIdTokenAsType() {
/// \brief Determine whether the given token can end a template argument.
static bool isEndOfTemplateArgument(Token Tok) {
- return Tok.is(tok::comma) || Tok.is(tok::greater) ||
- Tok.is(tok::greatergreater);
+ return Tok.isOneOf(tok::comma, tok::greater, tok::greatergreater);
}
/// \brief Parse a C++ template template argument.
@@ -1216,7 +1214,7 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) {
ConsumeToken();
// If we have a '>' or a ',' then this is a template argument list.
- return Tok.is(tok::greater) || Tok.is(tok::comma);
+ return Tok.isOneOf(tok::greater, tok::comma);
}
/// ParseTemplateArgumentList - Parse a C++ template-argument-list
@@ -1301,7 +1299,8 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
// To restore the context after late parsing.
- Sema::ContextRAII GlobalSavedContext(Actions, Actions.CurContext);
+ Sema::ContextRAII GlobalSavedContext(
+ Actions, Actions.Context.getTranslationUnitDecl());
SmallVector<ParseScope*, 4> TemplateParamScopeStack;
@@ -1337,8 +1336,8 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
// Consume the previously pushed token.
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
- assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
- && "Inline method not starting with '{', ':' or 'try'");
+ assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try) &&
+ "Inline method not starting with '{', ':' or 'try'");
// Parse the method body. Function body parsing code is similar enough
// to be re-used for method bodies as well.
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp
index abf16fa..d63cf24 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp
@@ -179,8 +179,8 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
ConsumeToken();
// Skip attributes.
- while (Tok.is(tok::l_square) || Tok.is(tok::kw___attribute) ||
- Tok.is(tok::kw___declspec) || Tok.is(tok::kw_alignas)) {
+ while (Tok.isOneOf(tok::l_square, tok::kw___attribute, tok::kw___declspec,
+ tok::kw_alignas)) {
if (Tok.is(tok::l_square)) {
ConsumeBracket();
if (!SkipUntil(tok::r_square))
@@ -195,8 +195,8 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
}
}
- if ((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
- Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id)) &&
+ if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype,
+ tok::annot_template_id) &&
TryAnnotateCXXScopeToken())
return TPResult::Error;
if (Tok.is(tok::annot_cxxscope))
@@ -289,7 +289,7 @@ Parser::TPResult Parser::TryParseInitDeclaratorList() {
return TPR;
// [GNU] simple-asm-expr[opt] attributes[opt]
- if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
+ if (Tok.isOneOf(tok::kw_asm, tok::kw___attribute))
return TPResult::True;
// initializer[opt]
@@ -370,8 +370,7 @@ bool Parser::isCXXConditionDeclaration() {
if (TPR == TPResult::Ambiguous) {
// '='
// [GNU] simple-asm-expr[opt] attributes[opt]
- if (Tok.is(tok::equal) ||
- Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
+ if (Tok.isOneOf(tok::equal, tok::kw_asm, tok::kw___attribute))
TPR = TPResult::True;
else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace))
TPR = TPResult::True;
@@ -448,7 +447,7 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
// the abstract declarator we encounter a '>', '>>' (in C++0x), or
// ',', this is a type-id. Otherwise, it's an expression.
} else if (Context == TypeIdAsTemplateArgument &&
- (Tok.is(tok::greater) || Tok.is(tok::comma) ||
+ (Tok.isOneOf(tok::greater, tok::comma) ||
(getLangOpts().CPlusPlus11 && Tok.is(tok::greatergreater)))) {
TPR = TPResult::True;
isAmbiguous = true;
@@ -624,18 +623,17 @@ Parser::isCXX11AttributeSpecifier(bool Disambiguate,
Parser::TPResult Parser::TryParsePtrOperatorSeq() {
while (true) {
- if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier))
+ if (Tok.isOneOf(tok::coloncolon, tok::identifier))
if (TryAnnotateCXXScopeToken(true))
return TPResult::Error;
- if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) ||
- Tok.is(tok::ampamp) ||
+ if (Tok.isOneOf(tok::star, tok::amp, tok::caret, tok::ampamp) ||
(Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) {
// ptr-operator
ConsumeToken();
- while (Tok.is(tok::kw_const) ||
- Tok.is(tok::kw_volatile) ||
- Tok.is(tok::kw_restrict))
+ while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict,
+ tok::kw___nonnull, tok::kw___nullable,
+ tok::kw___null_unspecified))
ConsumeToken();
} else {
return TPResult::True;
@@ -803,7 +801,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
if (Tok.is(tok::ellipsis))
ConsumeToken();
- if ((Tok.is(tok::identifier) || Tok.is(tok::kw_operator) ||
+ if ((Tok.isOneOf(tok::identifier, tok::kw_operator) ||
(Tok.is(tok::annot_cxxscope) && (NextToken().is(tok::identifier) ||
NextToken().is(tok::kw_operator)))) &&
mayHaveIdentifier) {
@@ -833,14 +831,9 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
// '(' declarator ')'
// '(' attributes declarator ')'
// '(' abstract-declarator ')'
- if (Tok.is(tok::kw___attribute) ||
- Tok.is(tok::kw___declspec) ||
- Tok.is(tok::kw___cdecl) ||
- Tok.is(tok::kw___stdcall) ||
- Tok.is(tok::kw___fastcall) ||
- Tok.is(tok::kw___thiscall) ||
- Tok.is(tok::kw___vectorcall) ||
- Tok.is(tok::kw___unaligned))
+ if (Tok.isOneOf(tok::kw___attribute, tok::kw___declspec, tok::kw___cdecl,
+ tok::kw___stdcall, tok::kw___fastcall, tok::kw___thiscall,
+ tok::kw___vectorcall, tok::kw___unaligned))
return TPResult::True; // attributes indicate declaration
TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);
if (TPR != TPResult::Ambiguous)
@@ -1015,9 +1008,8 @@ class TentativeParseCCC : public CorrectionCandidateCallback {
public:
TentativeParseCCC(const Token &Next) {
WantRemainingKeywords = false;
- WantTypeSpecifiers = Next.is(tok::l_paren) || Next.is(tok::r_paren) ||
- Next.is(tok::greater) || Next.is(tok::l_brace) ||
- Next.is(tok::identifier);
+ WantTypeSpecifiers = Next.isOneOf(tok::l_paren, tok::r_paren, tok::greater,
+ tok::l_brace, tok::identifier);
}
bool ValidateCandidate(const TypoCorrection &Candidate) override {
@@ -1201,8 +1193,8 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::coloncolon: { // ::foo::bar
const Token &Next = NextToken();
- if (Next.is(tok::kw_new) || // ::new
- Next.is(tok::kw_delete)) // ::delete
+ if (Next.isOneOf(tok::kw_new, // ::new
+ tok::kw_delete)) // ::delete
return TPResult::False;
}
// Fall through.
@@ -1284,6 +1276,9 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::kw___ptr32:
case tok::kw___forceinline:
case tok::kw___unaligned:
+ case tok::kw___nonnull:
+ case tok::kw___nullable:
+ case tok::kw___null_unspecified:
return TPResult::True;
// Borland
@@ -1603,12 +1598,10 @@ bool Parser::isCXXFunctionDeclarator(bool *IsAmbiguous) {
TPR = TPResult::False;
else {
const Token &Next = NextToken();
- if (Next.is(tok::amp) || Next.is(tok::ampamp) ||
- Next.is(tok::kw_const) || Next.is(tok::kw_volatile) ||
- Next.is(tok::kw_throw) || Next.is(tok::kw_noexcept) ||
- Next.is(tok::l_square) || isCXX11VirtSpecifier(Next) ||
- Next.is(tok::l_brace) || Next.is(tok::kw_try) ||
- Next.is(tok::equal) || Next.is(tok::arrow))
+ if (Next.isOneOf(tok::amp, tok::ampamp, tok::kw_const, tok::kw_volatile,
+ tok::kw_throw, tok::kw_noexcept, tok::l_square,
+ tok::l_brace, tok::kw_try, tok::equal, tok::arrow) ||
+ isCXX11VirtSpecifier(Next))
// The next token cannot appear after a constructor-style initializer,
// and can appear next in a function definition. This must be a function
// declarator.
@@ -1729,8 +1722,8 @@ Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration,
// parameter-declaration-clause, and the last param is missing its default
// argument.
if (VersusTemplateArgument)
- return (Tok.is(tok::equal) || Tok.is(tok::r_paren)) ? TPResult::True
- : TPResult::False;
+ return Tok.isOneOf(tok::equal, tok::r_paren) ? TPResult::True
+ : TPResult::False;
if (Tok.is(tok::equal)) {
// '=' assignment-expression
@@ -1783,13 +1776,11 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() {
return TPResult::Error;
// cv-qualifier-seq
- while (Tok.is(tok::kw_const) ||
- Tok.is(tok::kw_volatile) ||
- Tok.is(tok::kw_restrict) )
+ while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict))
ConsumeToken();
// ref-qualifier[opt]
- if (Tok.is(tok::amp) || Tok.is(tok::ampamp))
+ if (Tok.isOneOf(tok::amp, tok::ampamp))
ConsumeToken();
// exception-specification
diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
index 7ccd209..e32df95 100644
--- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
@@ -38,6 +38,26 @@ public:
return false;
}
};
+
+/// \brief RAIIObject to destroy the contents of a SmallVector of
+/// TemplateIdAnnotation pointers and clear the vector.
+class DestroyTemplateIdAnnotationsRAIIObj {
+ SmallVectorImpl<TemplateIdAnnotation *> &Container;
+
+public:
+ DestroyTemplateIdAnnotationsRAIIObj(
+ SmallVectorImpl<TemplateIdAnnotation *> &Container)
+ : Container(Container) {}
+
+ ~DestroyTemplateIdAnnotationsRAIIObj() {
+ for (SmallVectorImpl<TemplateIdAnnotation *>::iterator I =
+ Container.begin(),
+ E = Container.end();
+ I != E; ++I)
+ (*I)->Destroy();
+ Container.clear();
+ }
+};
} // end anonymous namespace
IdentifierInfo *Parser::getSEHExceptKeyword() {
@@ -414,6 +434,15 @@ Parser::~Parser() {
PP.clearCodeCompletionHandler();
+ if (getLangOpts().DelayedTemplateParsing &&
+ !PP.isIncrementalProcessingEnabled() && !TemplateIds.empty()) {
+ // If an ASTConsumer parsed delay-parsed templates in their
+ // HandleTranslationUnit() method, TemplateIds created there were not
+ // guarded by a DestroyTemplateIdAnnotationsRAIIObj object in
+ // ParseTopLevelDecl(). Destroy them here.
+ DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds);
+ }
+
assert(TemplateIds.empty() && "Still alive TemplateIdAnnotations around?");
}
@@ -434,6 +463,10 @@ void Parser::Initialize() {
ObjCTypeQuals[objc_oneway] = &PP.getIdentifierTable().get("oneway");
ObjCTypeQuals[objc_bycopy] = &PP.getIdentifierTable().get("bycopy");
ObjCTypeQuals[objc_byref] = &PP.getIdentifierTable().get("byref");
+ ObjCTypeQuals[objc_nonnull] = &PP.getIdentifierTable().get("nonnull");
+ ObjCTypeQuals[objc_nullable] = &PP.getIdentifierTable().get("nullable");
+ ObjCTypeQuals[objc_null_unspecified]
+ = &PP.getIdentifierTable().get("null_unspecified");
}
Ident_instancetype = nullptr;
@@ -490,26 +523,6 @@ void Parser::Initialize() {
ConsumeToken();
}
-namespace {
- /// \brief RAIIObject to destroy the contents of a SmallVector of
- /// TemplateIdAnnotation pointers and clear the vector.
- class DestroyTemplateIdAnnotationsRAIIObj {
- SmallVectorImpl<TemplateIdAnnotation *> &Container;
- public:
- DestroyTemplateIdAnnotationsRAIIObj(SmallVectorImpl<TemplateIdAnnotation *>
- &Container)
- : Container(Container) {}
-
- ~DestroyTemplateIdAnnotationsRAIIObj() {
- for (SmallVectorImpl<TemplateIdAnnotation *>::iterator I =
- Container.begin(), E = Container.end();
- I != E; ++I)
- (*I)->Destroy();
- Container.clear();
- }
- };
-}
-
void Parser::LateTemplateParserCleanupCallback(void *P) {
// While this RAII helper doesn't bracket any actual work, the destructor will
// clean up annotations that were created during ActOnEndOfTranslationUnit
@@ -541,8 +554,14 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
return false;
case tok::annot_module_begin:
+ Actions.ActOnModuleBegin(Tok.getLocation(), reinterpret_cast<Module *>(
+ Tok.getAnnotationValue()));
+ ConsumeToken();
+ return false;
+
case tok::annot_module_end:
- // FIXME: Update visibility based on the submodule we're in.
+ Actions.ActOnModuleEnd(Tok.getLocation(), reinterpret_cast<Module *>(
+ Tok.getAnnotationValue()));
ConsumeToken();
return false;
@@ -669,8 +688,18 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
SourceLocation StartLoc = Tok.getLocation();
SourceLocation EndLoc;
+
ExprResult Result(ParseSimpleAsm(&EndLoc));
+ // Check if GNU-style InlineAsm is disabled.
+ // Empty asm string is allowed because it will not introduce
+ // any assembly code.
+ if (!(getLangOpts().GNUAsm || Result.isInvalid())) {
+ const auto *SL = cast<StringLiteral>(Result.get());
+ if (!SL->getString().trim().empty())
+ Diag(StartLoc, diag::err_gnu_inline_asm_disabled);
+ }
+
ExpectAndConsume(tok::semi, diag::err_expected_after,
"top-level asm block");
@@ -1048,7 +1077,6 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
if (TryConsumeToken(tok::equal)) {
assert(getLangOpts().CPlusPlus && "Only C++ function definitions have '='");
- Actions.ActOnFinishFunctionBody(Res, nullptr, false);
bool Delete = false;
SourceLocation KWLoc;
@@ -1076,6 +1104,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
SkipUntil(tok::semi);
}
+ Stmt *GeneratedBody = Res ? Res->getBody() : nullptr;
+ Actions.ActOnFinishFunctionBody(Res, GeneratedBody, false);
return Res;
}
diff --git a/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h b/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h
index a0c9c1f..36d87eb 100644
--- a/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h
+++ b/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h
@@ -58,6 +58,12 @@ namespace clang {
Active = false;
}
}
+ SuppressAccessChecks(SuppressAccessChecks &&Other)
+ : S(Other.S), DiagnosticPool(std::move(Other.DiagnosticPool)),
+ State(Other.State), Active(Other.Active) {
+ Other.Active = false;
+ }
+ void operator=(SuppressAccessChecks &&Other) = delete;
void done() {
assert(Active && "trying to end an inactive suppression");
@@ -87,8 +93,8 @@ namespace clang {
Sema::ParsingDeclState State;
bool Popped;
- ParsingDeclRAIIObject(const ParsingDeclRAIIObject &) LLVM_DELETED_FUNCTION;
- void operator=(const ParsingDeclRAIIObject &) LLVM_DELETED_FUNCTION;
+ ParsingDeclRAIIObject(const ParsingDeclRAIIObject &) = delete;
+ void operator=(const ParsingDeclRAIIObject &) = delete;
public:
enum NoParent_t { NoParent };
@@ -244,8 +250,8 @@ namespace clang {
/// the way they used to be. This is used to handle __extension__ in the
/// parser.
class ExtensionRAIIObject {
- ExtensionRAIIObject(const ExtensionRAIIObject &) LLVM_DELETED_FUNCTION;
- void operator=(const ExtensionRAIIObject &) LLVM_DELETED_FUNCTION;
+ ExtensionRAIIObject(const ExtensionRAIIObject &) = delete;
+ void operator=(const ExtensionRAIIObject &) = delete;
DiagnosticsEngine &Diags;
public:
@@ -423,7 +429,13 @@ namespace clang {
if (P.Tok.is(Close)) {
LClose = (P.*Consumer)();
return false;
- }
+ } else if (P.Tok.is(tok::semi) && P.NextToken().is(Close)) {
+ SourceLocation SemiLoc = P.ConsumeToken();
+ P.Diag(SemiLoc, diag::err_unexpected_semi)
+ << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc));
+ LClose = (P.*Consumer)();
+ return false;
+ }
return diagnoseMissingClose();
}
OpenPOWER on IntegriCloud