aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse')
-rw-r--r--lib/Parse/CMakeLists.txt26
-rw-r--r--lib/Parse/ParseAST.cpp11
-rw-r--r--lib/Parse/ParseCXXInlineMethods.cpp142
-rw-r--r--lib/Parse/ParseDecl.cpp1611
-rw-r--r--lib/Parse/ParseDeclCXX.cpp845
-rw-r--r--lib/Parse/ParseExpr.cpp386
-rw-r--r--lib/Parse/ParseExprCXX.cpp464
-rw-r--r--lib/Parse/ParseInit.cpp84
-rw-r--r--lib/Parse/ParseObjc.cpp368
-rw-r--r--lib/Parse/ParseOpenMP.cpp513
-rw-r--r--lib/Parse/ParsePragma.cpp1062
-rw-r--r--lib/Parse/ParsePragma.h139
-rw-r--r--lib/Parse/ParseStmt.cpp1150
-rw-r--r--lib/Parse/ParseStmtAsm.cpp761
-rw-r--r--lib/Parse/ParseTemplate.cpp257
-rw-r--r--lib/Parse/ParseTentative.cpp400
-rw-r--r--lib/Parse/Parser.cpp439
-rw-r--r--lib/Parse/RAIIObjectsForParser.h16
18 files changed, 4993 insertions, 3681 deletions
diff --git a/lib/Parse/CMakeLists.txt b/lib/Parse/CMakeLists.txt
index 08bf4e196155..b868696eb6bb 100644
--- a/lib/Parse/CMakeLists.txt
+++ b/lib/Parse/CMakeLists.txt
@@ -1,3 +1,9 @@
+set(LLVM_LINK_COMPONENTS
+ MC
+ MCParser
+ Support
+ )
+
add_clang_library(clangParse
ParseAST.cpp
ParseCXXInlineMethods.cpp
@@ -10,28 +16,14 @@ add_clang_library(clangParse
ParseOpenMP.cpp
ParsePragma.cpp
ParseStmt.cpp
+ ParseStmtAsm.cpp
ParseTemplate.cpp
ParseTentative.cpp
Parser.cpp
- )
-add_dependencies(clangParse
- ClangAttrClasses
- ClangAttrIdentifierArg
- ClangAttrLateParsed
- ClangAttrList
- ClangAttrParsedAttrList
- ClangAttrTypeArg
- ClangCommentNodes
- ClangDeclNodes
- ClangDiagnosticCommon
- ClangDiagnosticParse
- ClangStmtNodes
- )
-
-target_link_libraries(clangParse
- clangBasic
+ LINK_LIBS
clangAST
+ clangBasic
clangLex
clangSema
)
diff --git a/lib/Parse/ParseAST.cpp b/lib/Parse/ParseAST.cpp
index 5678ece0c822..0f5a1b3ffbd6 100644
--- a/lib/Parse/ParseAST.cpp
+++ b/lib/Parse/ParseAST.cpp
@@ -23,9 +23,9 @@
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaConsumer.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include <cstdio>
+#include <memory>
using namespace clang;
@@ -36,7 +36,7 @@ class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry {
const Parser &P;
public:
PrettyStackTraceParserEntry(const Parser &p) : P(p) {}
- virtual void print(raw_ostream &OS) const;
+ void print(raw_ostream &OS) const override;
};
/// If a crash happens while the parser is active, print out a line indicating
@@ -88,7 +88,8 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
CodeCompleteConsumer *CompletionConsumer,
bool SkipFunctionBodies) {
- OwningPtr<Sema> S(new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer));
+ std::unique_ptr<Sema> S(
+ new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer));
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(S.get());
@@ -109,8 +110,8 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
ASTConsumer *Consumer = &S.getASTConsumer();
- OwningPtr<Parser> ParseOP(new Parser(S.getPreprocessor(), S,
- SkipFunctionBodies));
+ std::unique_ptr<Parser> ParseOP(
+ new Parser(S.getPreprocessor(), S, SkipFunctionBodies));
Parser &P = *ParseOP.get();
PrettyStackTraceParserEntry CrashInfo(P);
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 779230516532..30a9120a5106 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -19,13 +19,6 @@
#include "clang/Sema/Scope.h"
using namespace clang;
-/// Get the FunctionDecl for a function or function template decl.
-static FunctionDecl *getFunctionDecl(Decl *D) {
- if (FunctionDecl *fn = dyn_cast<FunctionDecl>(D))
- return fn;
- return cast<FunctionTemplateDecl>(D)->getTemplatedDecl();
-}
-
/// ParseCXXInlineMethodDef - We parsed and verified that the specified
/// Declarator is a well formed C++ inline method definition. Now lex its body
/// and store its tokens for parsing after the C++ class is complete.
@@ -42,8 +35,9 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
"Current token not a '{', ':', '=', or 'try'!");
MultiTemplateParamsArg TemplateParams(
- TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : 0,
- TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0);
+ TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data()
+ : nullptr,
+ TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0);
NamedDecl *FnD;
D.setFunctionDefinitionKind(DefinitionKind);
@@ -52,7 +46,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
TemplateParams);
else {
FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D,
- TemplateParams, 0,
+ TemplateParams, nullptr,
VS, ICIS_NoInit);
if (FnD) {
Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs);
@@ -69,30 +63,24 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
D.complete(FnD);
- if (Tok.is(tok::equal)) {
- ConsumeToken();
-
+ if (TryConsumeToken(tok::equal)) {
if (!FnD) {
SkipUntil(tok::semi);
- return 0;
+ return nullptr;
}
bool Delete = false;
SourceLocation KWLoc;
- if (Tok.is(tok::kw_delete)) {
- Diag(Tok, getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_deleted_function :
- diag::ext_deleted_function);
-
- KWLoc = ConsumeToken();
+ 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;
- } else if (Tok.is(tok::kw_default)) {
- Diag(Tok, getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_defaulted_function :
- diag::ext_defaulted_function);
-
- KWLoc = ConsumeToken();
+ } 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);
} else {
llvm_unreachable("function definition after = not 'delete' or 'default'");
@@ -102,9 +90,9 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
Diag(KWLoc, diag::err_default_delete_in_multiple_declaration)
<< Delete;
SkipUntil(tok::semi);
- } else {
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
- Delete ? "delete" : "default", tok::semi);
+ } else if (ExpectAndConsume(tok::semi, diag::err_expected_after,
+ Delete ? "delete" : "default")) {
+ SkipUntil(tok::semi);
}
return FnD;
@@ -115,9 +103,9 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
// the tokens and store them for parsing at the end of the translation unit.
if (getLangOpts().DelayedTemplateParsing &&
DefinitionKind == FDK_Definition &&
- !D.getDeclSpec().isConstexprSpecified() &&
- !(FnD && getFunctionDecl(FnD) &&
- getFunctionDecl(FnD)->getResultType()->getContainedAutoType()) &&
+ !D.getDeclSpec().isConstexprSpecified() &&
+ !(FnD && FnD->getAsFunction() &&
+ FnD->getAsFunction()->getReturnType()->getContainedAutoType()) &&
((Actions.CurContext->isDependentContext() ||
(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
TemplateInfo.Kind != ParsedTemplateInfo::ExplicitSpecialization)) &&
@@ -127,7 +115,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
LexTemplateFunctionForLateParsing(Toks);
if (FnD) {
- FunctionDecl *FD = getFunctionDecl(FnD);
+ FunctionDecl *FD = FnD->getAsFunction();
Actions.CheckForFunctionRedefinition(FD);
Actions.MarkAsLateParsedTemplate(FD, FnD, Toks);
}
@@ -179,7 +167,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
// If you remove this, you can remove the code that clears the flag
// after parsing the member.
if (D.getDeclSpec().isFriendSpecified()) {
- FunctionDecl *FD = getFunctionDecl(FnD);
+ FunctionDecl *FD = FnD->getAsFunction();
Actions.CheckForFunctionRedefinition(FD);
FD->setLateTemplateParsed(true);
}
@@ -275,7 +263,8 @@ void Parser::LateParsedMemberInitializer::ParseLexedMemberInitializers() {
/// delayed (such as default arguments) and parse them.
void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) {
bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
- ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
+ ParseScope ClassTemplateScope(this, Scope::TemplateParamScope,
+ HasTemplateScope);
TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
if (HasTemplateScope) {
Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
@@ -288,14 +277,16 @@ void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) {
ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope,
HasClassScope);
if (HasClassScope)
- Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate);
+ Actions.ActOnStartDelayedMemberDeclarations(getCurScope(),
+ Class.TagOrTemplate);
for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
Class.LateParsedDeclarations[i]->ParseLexedMethodDeclarations();
}
if (HasClassScope)
- Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate);
+ Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(),
+ Class.TagOrTemplate);
}
void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
@@ -315,7 +306,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
Scope::FunctionDeclarationScope | Scope::DeclScope);
for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {
// Introduce the parameter into scope.
- Actions.ActOnDelayedCXXMethodParameter(getCurScope(),
+ Actions.ActOnDelayedCXXMethodParameter(getCurScope(),
LM.DefaultArgs[I].Param);
if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) {
@@ -346,11 +337,10 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
} else
DefArgResult = ParseAssignmentExpression();
if (DefArgResult.isInvalid())
- Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param);
+ Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param,
+ EqualLoc);
else {
- if (Tok.is(tok::cxx_defaultarg_end))
- ConsumeToken();
- else {
+ if (!TryConsumeToken(tok::cxx_defaultarg_end)) {
// 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.
@@ -360,7 +350,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
(*Toks)[Toks->size() - 3].getLocation());
}
Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc,
- DefArgResult.take());
+ DefArgResult.get());
}
assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
@@ -372,7 +362,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
ConsumeAnyToken();
delete Toks;
- LM.DefaultArgs[I].Toks = 0;
+ LM.DefaultArgs[I].Toks = nullptr;
}
}
@@ -446,7 +436,7 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
// Error recovery.
if (!Tok.is(tok::l_brace)) {
FnScope.Exit();
- Actions.ActOnFinishFunctionBody(LM.D, 0);
+ Actions.ActOnFinishFunctionBody(LM.D, nullptr);
while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
ConsumeAnyToken();
return;
@@ -464,7 +454,8 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
ParseFunctionStatementBody(LM.D, FnScope);
// Clear the late-template-parsed bit if we set it before.
- if (LM.D) getFunctionDecl(LM.D)->setLateTemplateParsed(false);
+ if (LM.D)
+ LM.D->getAsFunction()->setLateTemplateParsed(false);
if (Tok.getLocation() != origLoc) {
// Due to parsing error, we either went over the cached tokens or
@@ -477,6 +468,9 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
ConsumeAnyToken();
}
+
+ if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(LM.D))
+ Actions.ActOnFinishInlineMethodDef(MD);
}
/// ParseLexedMemberInitializers - We finished parsing the member specification
@@ -536,10 +530,13 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) {
SourceLocation EqualLoc;
+ Actions.ActOnStartCXXInClassMemberInitializer();
+
ExprResult Init = ParseCXXMemberInitializer(MI.Field, /*IsFunction=*/false,
EqualLoc);
- Actions.ActOnCXXInClassMemberInitializer(MI.Field, EqualLoc, Init.release());
+ Actions.ActOnFinishCXXInClassMemberInitializer(MI.Field, EqualLoc,
+ Init.get());
// The next token should be our artificial terminating EOF token.
if (Tok.isNot(tok::eof)) {
@@ -580,6 +577,9 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
switch (Tok.getKind()) {
case tok::eof:
+ case tok::annot_module_begin:
+ case tok::annot_module_end:
+ case tok::annot_module_include:
// Ran out of tokens.
return false;
@@ -675,7 +675,7 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
/*StopAtSemi=*/true,
/*ConsumeFinalToken=*/false);
if (Tok.isNot(tok::l_brace))
- return Diag(Tok.getLocation(), diag::err_expected_lbrace);
+ return Diag(Tok.getLocation(), diag::err_expected) << tok::l_brace;
Toks.push_back(Tok);
ConsumeBrace();
@@ -708,8 +708,8 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
Toks.push_back(Tok);
ConsumeParen();
if (!ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/true)) {
- Diag(Tok.getLocation(), diag::err_expected_rparen);
- Diag(OpenLoc, diag::note_matching) << "(";
+ Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
+ Diag(OpenLoc, diag::note_matching) << tok::l_paren;
return true;
}
}
@@ -756,13 +756,15 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
/*ConsumeFinalToken=*/false)) {
// We're not just missing the initializer, we're also missing the
// function body!
- return Diag(Tok.getLocation(), diag::err_expected_lbrace);
+ return Diag(Tok.getLocation(), diag::err_expected) << tok::l_brace;
}
} else if (Tok.isNot(tok::l_paren) && Tok.isNot(tok::l_brace)) {
// We found something weird in a mem-initializer-id.
- return Diag(Tok.getLocation(), getLangOpts().CPlusPlus11
- ? diag::err_expected_lparen_or_lbrace
- : diag::err_expected_lparen);
+ if (getLangOpts().CPlusPlus11)
+ return Diag(Tok.getLocation(), diag::err_expected_either)
+ << tok::l_paren << tok::l_brace;
+ else
+ return Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
}
tok::TokenKind kind = Tok.getKind();
@@ -784,11 +786,10 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
// Grab the initializer (or the subexpression of the template argument).
// FIXME: If we support lambdas here, we'll need to set StopAtSemi to false
// if we might be inside the braces of a lambda-expression.
- if (!ConsumeAndStoreUntil(IsLParen ? tok::r_paren : tok::r_brace,
- Toks, /*StopAtSemi=*/true)) {
- Diag(Tok, IsLParen ? diag::err_expected_rparen :
- diag::err_expected_rbrace);
- Diag(OpenLoc, diag::note_matching) << (IsLParen ? "(" : "{");
+ tok::TokenKind CloseKind = IsLParen ? tok::r_paren : tok::r_brace;
+ if (!ConsumeAndStoreUntil(CloseKind, Toks, /*StopAtSemi=*/true)) {
+ Diag(Tok, diag::err_expected) << CloseKind;
+ Diag(OpenLoc, diag::note_matching) << kind;
return true;
}
@@ -822,7 +823,8 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
ConsumeBrace();
return false;
} else if (!MightBeTemplateArgument) {
- return Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma);
+ return Diag(Tok.getLocation(), diag::err_expected_either) << tok::l_brace
+ << tok::comma;
}
}
}
@@ -836,8 +838,9 @@ bool Parser::ConsumeAndStoreConditional(CachedTokens &Toks) {
ConsumeToken();
while (Tok.isNot(tok::colon)) {
- if (!ConsumeAndStoreUntil(tok::question, tok::colon, Toks, /*StopAtSemi*/true,
- /*ConsumeFinalToken*/false))
+ if (!ConsumeAndStoreUntil(tok::question, tok::colon, Toks,
+ /*StopAtSemi=*/true,
+ /*ConsumeFinalToken=*/false))
return false;
// If we found a nested conditional, consume it.
@@ -925,15 +928,15 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks,
? tok::semi : tok::r_paren);
Sema::TentativeAnalysisScope Scope(Actions);
- TPResult Result = TPResult::Error();
+ TPResult Result = TPResult::Error;
ConsumeToken();
switch (CIK) {
case CIK_DefaultInitializer:
Result = TryParseInitDeclaratorList();
// If we parsed a complete, ambiguous init-declarator-list, this
// is only syntactically-valid if it's followed by a semicolon.
- if (Result == TPResult::Ambiguous() && Tok.isNot(tok::semi))
- Result = TPResult::False();
+ if (Result == TPResult::Ambiguous && Tok.isNot(tok::semi))
+ Result = TPResult::False;
break;
case CIK_DefaultArgument:
@@ -942,13 +945,13 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks,
&InvalidAsDeclaration, /*VersusTemplateArgument*/true);
// If this is an expression or a declaration with a missing
// 'typename', assume it's not a declaration.
- if (Result == TPResult::Ambiguous() && InvalidAsDeclaration)
- Result = TPResult::False();
+ if (Result == TPResult::Ambiguous && InvalidAsDeclaration)
+ Result = TPResult::False;
break;
}
// If what follows could be a declaration, it is a declaration.
- if (Result != TPResult::False() && Result != TPResult::Error()) {
+ if (Result != TPResult::False && Result != TPResult::Error) {
PA.Revert();
return true;
}
@@ -965,6 +968,9 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks,
goto consume_token;
case tok::eof:
+ case tok::annot_module_begin:
+ case tok::annot_module_end:
+ case tok::annot_module_include:
// Ran out of tokens.
return false;
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 7b8093408bfd..62d43768bff4 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -13,10 +13,12 @@
#include "clang/Parse/Parser.h"
#include "RAIIObjectsForParser.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/Attributes.h"
#include "clang/Basic/CharInfo.h"
-#include "clang/Basic/OpenCL.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ParsedTemplate.h"
@@ -51,7 +53,7 @@ TypeResult Parser::ParseTypeName(SourceRange *Range,
DS.addAttributes(Attrs->getList());
ParseSpecifierQualifierList(DS, AS, DSC);
if (OwnedType)
- *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : 0;
+ *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : nullptr;
// Parse the abstract-declarator, if present.
Declarator DeclaratorInfo(DS, Context);
@@ -69,9 +71,11 @@ TypeResult Parser::ParseTypeName(SourceRange *Range,
/// isAttributeLateParsed - Return true if the attribute has arguments that
/// require late parsing.
static bool isAttributeLateParsed(const IdentifierInfo &II) {
+#define CLANG_ATTR_LATE_PARSED_LIST
return llvm::StringSwitch<bool>(II.getName())
-#include "clang/Parse/AttrLateParsed.inc"
+#include "clang/Parse/AttrParserStringSwitches.inc"
.Default(false);
+#undef CLANG_ATTR_LATE_PARSED_LIST
}
/// ParseGNUAttributes - Parse a non-empty attributes list.
@@ -117,7 +121,8 @@ static bool isAttributeLateParsed(const IdentifierInfo &II) {
/// We follow the C++ model, but don't allow junk after the identifier.
void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
SourceLocation *endLoc,
- LateParsedAttrList *LateAttrs) {
+ LateParsedAttrList *LateAttrs,
+ Declarator *D) {
assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!");
while (Tok.is(tok::kw___attribute)) {
@@ -132,49 +137,54 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
return;
}
// Parse the attribute-list. e.g. __attribute__(( weak, alias("__f") ))
- while (Tok.is(tok::identifier) || isDeclarationSpecifier() ||
- Tok.is(tok::comma)) {
- if (Tok.is(tok::comma)) {
- // allows for empty/non-empty attributes. ((__vector_size__(16),,,,))
- ConsumeToken();
+ while (true) {
+ // Allow empty/non-empty attributes. ((__vector_size__(16),,,,))
+ if (TryConsumeToken(tok::comma))
continue;
- }
- // we have an identifier or declaration specifier (const, int, etc.)
+
+ // Expect an identifier or declaration specifier (const, int, etc.)
+ if (Tok.isNot(tok::identifier) && !isDeclarationSpecifier())
+ break;
+
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
- if (Tok.is(tok::l_paren)) {
- // handle "parameterized" attributes
- if (LateAttrs && isAttributeLateParsed(*AttrName)) {
- LateParsedAttribute *LA =
- new LateParsedAttribute(this, *AttrName, AttrNameLoc);
- LateAttrs->push_back(LA);
-
- // Attributes in a class are parsed at the end of the class, along
- // with other late-parsed declarations.
- if (!ClassStack.empty() && !LateAttrs->parseSoon())
- getCurrentClass().LateParsedDeclarations.push_back(LA);
-
- // consume everything up to and including the matching right parens
- ConsumeAndStoreUntil(tok::r_paren, LA->Toks, true, false);
-
- Token Eof;
- Eof.startToken();
- Eof.setLocation(Tok.getLocation());
- LA->Toks.push_back(Eof);
- } else {
- ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc,
- 0, SourceLocation(), AttributeList::AS_GNU);
- }
- } else {
- attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ if (Tok.isNot(tok::l_paren)) {
+ attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
AttributeList::AS_GNU);
+ continue;
+ }
+
+ // Handle "parameterized" attributes
+ if (!LateAttrs || !isAttributeLateParsed(*AttrName)) {
+ ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc, nullptr,
+ SourceLocation(), AttributeList::AS_GNU, D);
+ continue;
}
+
+ // Handle attributes with arguments that require late parsing.
+ LateParsedAttribute *LA =
+ new LateParsedAttribute(this, *AttrName, AttrNameLoc);
+ LateAttrs->push_back(LA);
+
+ // Attributes in a class are parsed at the end of the class, along
+ // with other late-parsed declarations.
+ if (!ClassStack.empty() && !LateAttrs->parseSoon())
+ getCurrentClass().LateParsedDeclarations.push_back(LA);
+
+ // consume everything up to and including the matching right parens
+ ConsumeAndStoreUntil(tok::r_paren, LA->Toks, true, false);
+
+ Token Eof;
+ Eof.startToken();
+ Eof.setLocation(Tok.getLocation());
+ LA->Toks.push_back(Eof);
}
- if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
+
+ if (ExpectAndConsume(tok::r_paren))
SkipUntil(tok::r_paren, StopAtSemi);
SourceLocation Loc = Tok.getLocation();
- if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
+ if (ExpectAndConsume(tok::r_paren))
SkipUntil(tok::r_paren, StopAtSemi);
if (endLoc)
*endLoc = Loc;
@@ -190,16 +200,30 @@ static StringRef normalizeAttrName(StringRef Name) {
/// \brief Determine whether the given attribute has an identifier argument.
static bool attributeHasIdentifierArg(const IdentifierInfo &II) {
+#define CLANG_ATTR_IDENTIFIER_ARG_LIST
return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
-#include "clang/Parse/AttrIdentifierArg.inc"
+#include "clang/Parse/AttrParserStringSwitches.inc"
.Default(false);
+#undef CLANG_ATTR_IDENTIFIER_ARG_LIST
}
/// \brief Determine whether the given attribute parses a type argument.
static bool attributeIsTypeArgAttr(const IdentifierInfo &II) {
+#define CLANG_ATTR_TYPE_ARG_LIST
+ return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
+#include "clang/Parse/AttrParserStringSwitches.inc"
+ .Default(false);
+#undef CLANG_ATTR_TYPE_ARG_LIST
+}
+
+/// \brief Determine whether the given attribute requires parsing its arguments
+/// in an unevaluated context or not.
+static bool attributeParsedArgsUnevaluated(const IdentifierInfo &II) {
+#define CLANG_ATTR_ARG_CONTEXT_LIST
return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
-#include "clang/Parse/AttrTypeArg.inc"
+#include "clang/Parse/AttrParserStringSwitches.inc"
.Default(false);
+#undef CLANG_ATTR_ARG_CONTEXT_LIST
}
IdentifierLoc *Parser::ParseIdentifierLoc() {
@@ -214,7 +238,10 @@ IdentifierLoc *Parser::ParseIdentifierLoc() {
void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs,
- SourceLocation *EndLoc) {
+ SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc,
+ AttributeList::Syntax Syntax) {
BalancedDelimiterTracker Parens(*this, tok::l_paren);
Parens.consumeOpen();
@@ -230,61 +257,26 @@ void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName,
if (T.isUsable())
Attrs.addNewTypeAttr(&AttrName,
- SourceRange(AttrNameLoc, Parens.getCloseLocation()), 0,
- AttrNameLoc, T.get(), AttributeList::AS_GNU);
+ SourceRange(AttrNameLoc, Parens.getCloseLocation()),
+ ScopeName, ScopeLoc, T.get(), Syntax);
else
Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, Parens.getCloseLocation()),
- 0, AttrNameLoc, 0, 0, AttributeList::AS_GNU);
+ ScopeName, ScopeLoc, nullptr, 0, Syntax);
}
-/// Parse the arguments to a parameterized GNU attribute or
-/// a C++11 attribute in "gnu" namespace.
-void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
- SourceLocation AttrNameLoc,
- ParsedAttributes &Attrs,
- SourceLocation *EndLoc,
- IdentifierInfo *ScopeName,
- SourceLocation ScopeLoc,
- AttributeList::Syntax Syntax) {
-
- assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
-
- AttributeList::Kind AttrKind =
- AttributeList::getKind(AttrName, ScopeName, Syntax);
-
- // Availability attributes have their own grammar.
- // FIXME: All these cases fail to pass in the syntax and scope, and might be
- // written as C++11 gnu:: attributes.
- if (AttrKind == AttributeList::AT_Availability) {
- ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc);
- return;
- }
- // Thread safety attributes are parsed in an unevaluated context.
- // FIXME: Share the bulk of the parsing code here and just pull out
- // the unevaluated context.
- if (IsThreadSafetyAttribute(AttrName->getName())) {
- ParseThreadSafetyAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc);
- return;
- }
- // Type safety attributes have their own grammar.
- if (AttrKind == AttributeList::AT_TypeTagForDatatype) {
- ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc);
- return;
- }
- // Some attributes expect solely a type parameter.
- if (attributeIsTypeArgAttr(*AttrName)) {
- ParseAttributeWithTypeArg(*AttrName, AttrNameLoc, Attrs, EndLoc);
- return;
- }
-
+unsigned Parser::ParseAttributeArgsCommon(
+ IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc, AttributeList::Syntax Syntax) {
// Ignore the left paren location for now.
ConsumeParen();
ArgsVector ArgExprs;
-
if (Tok.is(tok::identifier)) {
// If this attribute wants an 'identifier' argument, make it so.
bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName);
+ AttributeList::Kind AttrKind =
+ AttributeList::getKind(AttrName, ScopeName, Syntax);
// If we don't know how to parse this attribute, but this is the only
// token in this argument, assume it's meant to be an identifier.
@@ -304,112 +296,117 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
ConsumeToken();
// Parse the non-empty comma-separated list of expressions.
- while (1) {
+ do {
+ std::unique_ptr<EnterExpressionEvaluationContext> Unevaluated;
+ if (attributeParsedArgsUnevaluated(*AttrName))
+ Unevaluated.reset(
+ new EnterExpressionEvaluationContext(Actions, Sema::Unevaluated));
+
ExprResult ArgExpr(ParseAssignmentExpression());
if (ArgExpr.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
- return;
+ return 0;
}
- ArgExprs.push_back(ArgExpr.release());
- if (Tok.isNot(tok::comma))
- break;
- ConsumeToken(); // Eat the comma, move to the next argument
- }
+ ArgExprs.push_back(ArgExpr.get());
+ // Eat the comma, move to the next argument
+ } while (TryConsumeToken(tok::comma));
}
SourceLocation RParen = Tok.getLocation();
- if (!ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) {
+ if (!ExpectAndConsume(tok::r_paren)) {
SourceLocation AttrLoc = ScopeLoc.isValid() ? ScopeLoc : AttrNameLoc;
Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc,
ArgExprs.data(), ArgExprs.size(), Syntax);
}
+
+ if (EndLoc)
+ *EndLoc = RParen;
+
+ return static_cast<unsigned>(ArgExprs.size());
}
-/// \brief Parses a single argument for a declspec, including the
-/// surrounding parens.
-void Parser::ParseMicrosoftDeclSpecWithSingleArg(IdentifierInfo *AttrName,
- SourceLocation AttrNameLoc,
- ParsedAttributes &Attrs)
-{
- BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen_after,
- AttrName->getNameStart(), tok::r_paren))
- return;
+/// Parse the arguments to a parameterized GNU attribute or
+/// a C++11 attribute in "gnu" namespace.
+void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs,
+ SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc,
+ AttributeList::Syntax Syntax,
+ Declarator *D) {
- ExprResult ArgExpr(ParseConstantExpression());
- if (ArgExpr.isInvalid()) {
- T.skipToEnd();
+ assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
+
+ AttributeList::Kind AttrKind =
+ AttributeList::getKind(AttrName, ScopeName, Syntax);
+
+ if (AttrKind == AttributeList::AT_Availability) {
+ ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
+ ScopeLoc, Syntax);
+ return;
+ } else if (AttrKind == AttributeList::AT_ObjCBridgeRelated) {
+ ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
+ ScopeName, ScopeLoc, Syntax);
+ return;
+ } else if (AttrKind == AttributeList::AT_TypeTagForDatatype) {
+ ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
+ ScopeName, ScopeLoc, Syntax);
+ return;
+ } else if (attributeIsTypeArgAttr(*AttrName)) {
+ ParseAttributeWithTypeArg(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
+ ScopeLoc, Syntax);
return;
}
- ArgsUnion ExprList = ArgExpr.take();
- Attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, &ExprList, 1,
- AttributeList::AS_Declspec);
- T.consumeClose();
-}
+ // These may refer to the function arguments, but need to be parsed early to
+ // participate in determining whether it's a redeclaration.
+ std::unique_ptr<ParseScope> PrototypeScope;
+ if (AttrName->isStr("enable_if") && D && D->isFunctionDeclarator()) {
+ DeclaratorChunk::FunctionTypeInfo FTI = D->getFunctionTypeInfo();
+ PrototypeScope.reset(new ParseScope(this, Scope::FunctionPrototypeScope |
+ Scope::FunctionDeclarationScope |
+ Scope::DeclScope));
+ for (unsigned i = 0; i != FTI.NumParams; ++i) {
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
+ Actions.ActOnReenterCXXMethodParameter(getCurScope(), Param);
+ }
+ }
-/// \brief Determines whether a declspec is a "simple" one requiring no
-/// arguments.
-bool Parser::IsSimpleMicrosoftDeclSpec(IdentifierInfo *Ident) {
- return llvm::StringSwitch<bool>(Ident->getName())
- .Case("dllimport", true)
- .Case("dllexport", true)
- .Case("noreturn", true)
- .Case("nothrow", true)
- .Case("noinline", true)
- .Case("naked", true)
- .Case("appdomain", true)
- .Case("process", true)
- .Case("jitintrinsic", true)
- .Case("noalias", true)
- .Case("restrict", true)
- .Case("novtable", true)
- .Case("selectany", true)
- .Case("thread", true)
- .Case("safebuffers", true )
- .Default(false);
+ ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
+ ScopeLoc, Syntax);
}
-/// \brief Attempts to parse a declspec which is not simple (one that takes
-/// parameters). Will return false if we properly handled the declspec, or
-/// true if it is an unknown declspec.
-void Parser::ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident,
- SourceLocation Loc,
- ParsedAttributes &Attrs) {
- // Try to handle the easy case first -- these declspecs all take a single
- // parameter as their argument.
- if (llvm::StringSwitch<bool>(Ident->getName())
- .Case("uuid", true)
- .Case("align", true)
- .Case("allocate", true)
- .Default(false)) {
- ParseMicrosoftDeclSpecWithSingleArg(Ident, Loc, Attrs);
- } else if (Ident->getName() == "deprecated") {
- // The deprecated declspec has an optional single argument, so we will
- // check for a l-paren to decide whether we should parse an argument or
- // not.
- if (Tok.getKind() == tok::l_paren)
- ParseMicrosoftDeclSpecWithSingleArg(Ident, Loc, Attrs);
- else
- Attrs.addNew(Ident, Loc, 0, Loc, 0, 0, AttributeList::AS_Declspec);
- } else if (Ident->getName() == "property") {
+bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs) {
+ // If the attribute isn't known, we will not attempt to parse any
+ // arguments.
+ if (!hasAttribute(AttrSyntax::Declspec, nullptr, AttrName,
+ getTargetInfo().getTriple(), getLangOpts())) {
+ // Eat the left paren, then skip to the ending right paren.
+ ConsumeParen();
+ SkipUntil(tok::r_paren);
+ return false;
+ }
+
+ SourceLocation OpenParenLoc = Tok.getLocation();
+
+ if (AttrName->getName() == "property") {
// The property declspec is more complex in that it can take one or two
// assignment expressions as a parameter, but the lhs of the assignment
// must be named get or put.
- if (Tok.isNot(tok::l_paren)) {
- Diag(Tok.getLocation(), diag::err_expected_lparen_after)
- << Ident->getNameStart();
- return;
- }
+
BalancedDelimiterTracker T(*this, tok::l_paren);
T.expectAndConsume(diag::err_expected_lparen_after,
- Ident->getNameStart(), tok::r_paren);
+ AttrName->getNameStart(), tok::r_paren);
enum AccessorKind {
AK_Invalid = -1,
- AK_Put = 0, AK_Get = 1 // indices into AccessorNames
+ AK_Put = 0,
+ AK_Get = 1 // indices into AccessorNames
};
- IdentifierInfo *AccessorNames[] = { 0, 0 };
+ IdentifierInfo *AccessorNames[] = {nullptr, nullptr};
bool HasInvalidAccessor = false;
// Parse the accessor specifications.
@@ -418,8 +415,9 @@ void Parser::ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident,
if (!Tok.is(tok::identifier)) {
// If the user wrote a completely empty list, use a special diagnostic.
if (Tok.is(tok::r_paren) && !HasInvalidAccessor &&
- AccessorNames[AK_Put] == 0 && AccessorNames[AK_Get] == 0) {
- Diag(Loc, diag::err_ms_property_no_getter_or_putter);
+ AccessorNames[AK_Put] == nullptr &&
+ AccessorNames[AK_Get] == nullptr) {
+ Diag(AttrNameLoc, diag::err_ms_property_no_getter_or_putter);
break;
}
@@ -435,39 +433,38 @@ void Parser::ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident,
} else if (KindStr == "put") {
Kind = AK_Put;
- // Recover from the common mistake of using 'set' instead of 'put'.
+ // Recover from the common mistake of using 'set' instead of 'put'.
} else if (KindStr == "set") {
Diag(KindLoc, diag::err_ms_property_has_set_accessor)
- << FixItHint::CreateReplacement(KindLoc, "put");
+ << FixItHint::CreateReplacement(KindLoc, "put");
Kind = AK_Put;
- // Handle the mistake of forgetting the accessor kind by skipping
- // this accessor.
+ // Handle the mistake of forgetting the accessor kind by skipping
+ // this accessor.
} else if (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)) {
Diag(KindLoc, diag::err_ms_property_missing_accessor_kind);
ConsumeToken();
HasInvalidAccessor = true;
goto next_property_accessor;
- // Otherwise, complain about the unknown accessor kind.
+ // Otherwise, complain about the unknown accessor kind.
} else {
Diag(KindLoc, diag::err_ms_property_unknown_accessor);
HasInvalidAccessor = true;
Kind = AK_Invalid;
// Try to keep parsing unless it doesn't look like an accessor spec.
- if (!NextToken().is(tok::equal)) break;
+ if (!NextToken().is(tok::equal))
+ break;
}
// Consume the identifier.
ConsumeToken();
// Consume the '='.
- if (Tok.is(tok::equal)) {
- ConsumeToken();
- } else {
+ if (!TryConsumeToken(tok::equal)) {
Diag(Tok.getLocation(), diag::err_ms_property_expected_equal)
- << KindStr;
+ << KindStr;
break;
}
@@ -479,7 +476,7 @@ void Parser::ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident,
if (Kind == AK_Invalid) {
// Just drop invalid accessors.
- } else if (AccessorNames[Kind] != NULL) {
+ } else if (AccessorNames[Kind] != nullptr) {
// Complain about the repeated accessor, ignore it, and keep parsing.
Diag(KindLoc, diag::err_ms_property_duplicate_accessor) << KindStr;
} else {
@@ -489,41 +486,38 @@ void Parser::ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident,
next_property_accessor:
// Keep processing accessors until we run out.
- if (Tok.is(tok::comma)) {
- ConsumeAnyToken();
+ if (TryConsumeToken(tok::comma))
continue;
// If we run into the ')', stop without consuming it.
- } else if (Tok.is(tok::r_paren)) {
+ if (Tok.is(tok::r_paren))
break;
- } else {
- Diag(Tok.getLocation(), diag::err_ms_property_expected_comma_or_rparen);
- break;
- }
+
+ Diag(Tok.getLocation(), diag::err_ms_property_expected_comma_or_rparen);
+ break;
}
// Only add the property attribute if it was well-formed.
- if (!HasInvalidAccessor) {
- Attrs.addNewPropertyAttr(Ident, Loc, 0, SourceLocation(),
+ if (!HasInvalidAccessor)
+ Attrs.addNewPropertyAttr(AttrName, AttrNameLoc, nullptr, SourceLocation(),
AccessorNames[AK_Get], AccessorNames[AK_Put],
AttributeList::AS_Declspec);
- }
T.skipToEnd();
- } else {
- // We don't recognize this as a valid declspec, but instead of creating the
- // attribute and allowing sema to warn about it, we will warn here instead.
- // This is because some attributes have multiple spellings, but we need to
- // disallow that for declspecs (such as align vs aligned). If we made the
- // attribute, we'd have to split the valid declspec spelling logic into
- // both locations.
- Diag(Loc, diag::warn_ms_declspec_unknown) << Ident;
-
- // If there's an open paren, we should eat the open and close parens under
- // the assumption that this unknown declspec has parameters.
- BalancedDelimiterTracker T(*this, tok::l_paren);
- if (!T.consumeOpen())
- T.skipToEnd();
+ return !HasInvalidAccessor;
}
+
+ unsigned NumArgs =
+ ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr,
+ SourceLocation(), AttributeList::AS_Declspec);
+
+ // If this attribute's args were parsed, and it was expected to have
+ // arguments but none were provided, emit a diagnostic.
+ const AttributeList *Attr = Attrs.getList();
+ if (Attr && Attr->getMaxArgs() && !NumArgs) {
+ Diag(OpenParenLoc, diag::err_attribute_requires_arguments) << AttrName;
+ return false;
+ }
+ return true;
}
/// [MS] decl-specifier:
@@ -543,7 +537,11 @@ void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &Attrs) {
// An empty declspec is perfectly legal and should not warn. Additionally,
// you can specify multiple attributes per declspec.
- while (Tok.getKind() != tok::r_paren) {
+ 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;
@@ -571,17 +569,19 @@ void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &Attrs) {
AttrNameLoc = ConsumeToken();
}
- if (IsString || IsSimpleMicrosoftDeclSpec(AttrName))
- // If we have a generic string, we will allow it because there is no
- // documented list of allowable string declspecs, but we know they exist
- // (for instance, SAL declspecs in older versions of MSVC).
- //
- // Alternatively, if the identifier is a simple one, then it requires no
- // arguments and can be turned into an attribute directly.
- Attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ 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();
+
+ if (!AttrHandled)
+ Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
AttributeList::AS_Declspec);
- else
- ParseComplexMicrosoftDeclSpec(AttrName, AttrNameLoc, Attrs);
}
T.consumeClose();
}
@@ -595,7 +595,7 @@ void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) {
Tok.is(tok::kw___sptr) || Tok.is(tok::kw___uptr)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
- attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
AttributeList::AS_Keyword);
}
}
@@ -605,7 +605,7 @@ void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) {
while (Tok.is(tok::kw___pascal)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
- attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
AttributeList::AS_Keyword);
}
}
@@ -615,61 +615,16 @@ void Parser::ParseOpenCLAttributes(ParsedAttributes &attrs) {
while (Tok.is(tok::kw___kernel)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
- attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
AttributeList::AS_Keyword);
}
}
-void Parser::ParseOpenCLQualifiers(DeclSpec &DS) {
- // FIXME: The mapping from attribute spelling to semantics should be
- // performed in Sema, not here.
- SourceLocation Loc = Tok.getLocation();
- switch(Tok.getKind()) {
- // OpenCL qualifiers:
- case tok::kw___private:
- case tok::kw_private:
- DS.getAttributes().addNewInteger(
- Actions.getASTContext(),
- PP.getIdentifierInfo("address_space"), Loc, 0);
- break;
-
- case tok::kw___global:
- DS.getAttributes().addNewInteger(
- Actions.getASTContext(),
- PP.getIdentifierInfo("address_space"), Loc, LangAS::opencl_global);
- break;
-
- case tok::kw___local:
- DS.getAttributes().addNewInteger(
- Actions.getASTContext(),
- PP.getIdentifierInfo("address_space"), Loc, LangAS::opencl_local);
- break;
-
- case tok::kw___constant:
- DS.getAttributes().addNewInteger(
- Actions.getASTContext(),
- PP.getIdentifierInfo("address_space"), Loc, LangAS::opencl_constant);
- break;
-
- case tok::kw___read_only:
- DS.getAttributes().addNewInteger(
- Actions.getASTContext(),
- PP.getIdentifierInfo("opencl_image_access"), Loc, CLIA_read_only);
- break;
-
- case tok::kw___write_only:
- DS.getAttributes().addNewInteger(
- Actions.getASTContext(),
- PP.getIdentifierInfo("opencl_image_access"), Loc, CLIA_write_only);
- break;
-
- case tok::kw___read_write:
- DS.getAttributes().addNewInteger(
- Actions.getASTContext(),
- PP.getIdentifierInfo("opencl_image_access"), Loc, CLIA_read_write);
- break;
- default: break;
- }
+void Parser::ParseOpenCLQualifiers(ParsedAttributes &Attrs) {
+ IdentifierInfo *AttrName = Tok.getIdentifierInfo();
+ SourceLocation AttrNameLoc = Tok.getLocation();
+ Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
+ AttributeList::AS_Keyword);
}
/// \brief Parse a version number.
@@ -804,7 +759,10 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) {
void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
SourceLocation AvailabilityLoc,
ParsedAttributes &attrs,
- SourceLocation *endLoc) {
+ SourceLocation *endLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc,
+ AttributeList::Syntax Syntax) {
enum { Introduced, Deprecated, Obsoleted, Unknown };
AvailabilityChange Changes[Unknown];
ExprResult MessageExpr;
@@ -812,7 +770,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
// Opening '('.
BalancedDelimiterTracker T(*this, tok::l_paren);
if (T.consumeOpen()) {
- Diag(Tok, diag::err_expected_lparen);
+ Diag(Tok, diag::err_expected) << tok::l_paren;
return;
}
@@ -825,8 +783,10 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
IdentifierLoc *Platform = ParseIdentifierLoc();
// Parse the ',' following the platform name.
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", tok::r_paren))
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return;
+ }
// If we haven't grabbed the pointers for the identifiers
// "introduced", "deprecated", and "obsoleted", do so now.
@@ -855,29 +815,34 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
<< Keyword << SourceRange(UnavailableLoc);
}
UnavailableLoc = KeywordLoc;
-
- if (Tok.isNot(tok::comma))
- break;
-
- ConsumeToken();
continue;
}
if (Tok.isNot(tok::equal)) {
- Diag(Tok, diag::err_expected_equal_after)
- << Keyword;
+ Diag(Tok, diag::err_expected_after) << Keyword << tok::equal;
SkipUntil(tok::r_paren, StopAtSemi);
return;
}
ConsumeToken();
if (Keyword == Ident_message) {
- if (Tok.isNot(tok::string_literal)) { // Also reject wide string literals.
+ if (Tok.isNot(tok::string_literal)) {
Diag(Tok, diag::err_expected_string_literal)
<< /*Source='availability attribute'*/2;
SkipUntil(tok::r_paren, StopAtSemi);
return;
}
MessageExpr = ParseStringLiteralExpression();
+ // Also reject wide string literals.
+ if (StringLiteral *MessageStringLiteral =
+ cast_or_null<StringLiteral>(MessageExpr.get())) {
+ if (MessageStringLiteral->getCharByteWidth() != 1) {
+ Diag(MessageStringLiteral->getSourceRange().getBegin(),
+ diag::err_expected_string_literal)
+ << /*Source='availability attribute'*/ 2;
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+ }
break;
}
@@ -915,11 +880,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
<< Keyword << VersionRange;
}
- if (Tok.isNot(tok::comma))
- break;
-
- ConsumeToken();
- } while (true);
+ } while (TryConsumeToken(tok::comma));
// Closing ')'.
if (T.consumeClose())
@@ -950,15 +911,97 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
// Record this attribute
attrs.addNew(&Availability,
SourceRange(AvailabilityLoc, T.getCloseLocation()),
- 0, AvailabilityLoc,
+ ScopeName, ScopeLoc,
Platform,
Changes[Introduced],
Changes[Deprecated],
Changes[Obsoleted],
- UnavailableLoc, MessageExpr.take(),
- AttributeList::AS_GNU);
+ UnavailableLoc, MessageExpr.get(),
+ Syntax);
}
+/// \brief Parse the contents of the "objc_bridge_related" attribute.
+/// objc_bridge_related '(' related_class ',' opt-class_method ',' opt-instance_method ')'
+/// related_class:
+/// Identifier
+///
+/// opt-class_method:
+/// Identifier: | <empty>
+///
+/// opt-instance_method:
+/// Identifier | <empty>
+///
+void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
+ SourceLocation ObjCBridgeRelatedLoc,
+ ParsedAttributes &attrs,
+ SourceLocation *endLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc,
+ AttributeList::Syntax Syntax) {
+ // Opening '('.
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ if (T.consumeOpen()) {
+ Diag(Tok, diag::err_expected) << tok::l_paren;
+ return;
+ }
+
+ // Parse the related class name.
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_objcbridge_related_expected_related_class);
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+ IdentifierLoc *RelatedClass = ParseIdentifierLoc();
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+
+ // Parse optional class method name.
+ IdentifierLoc *ClassMethod = nullptr;
+ if (Tok.is(tok::identifier)) {
+ ClassMethod = ParseIdentifierLoc();
+ if (!TryConsumeToken(tok::colon)) {
+ Diag(Tok, diag::err_objcbridge_related_selector_name);
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+ }
+ if (!TryConsumeToken(tok::comma)) {
+ if (Tok.is(tok::colon))
+ Diag(Tok, diag::err_objcbridge_related_selector_name);
+ else
+ Diag(Tok, diag::err_expected) << tok::comma;
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+
+ // Parse optional instance method name.
+ IdentifierLoc *InstanceMethod = nullptr;
+ if (Tok.is(tok::identifier))
+ InstanceMethod = ParseIdentifierLoc();
+ else if (Tok.isNot(tok::r_paren)) {
+ Diag(Tok, diag::err_expected) << tok::r_paren;
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+
+ // Closing ')'.
+ if (T.consumeClose())
+ return;
+
+ if (endLoc)
+ *endLoc = T.getCloseLocation();
+
+ // Record this attribute
+ attrs.addNew(&ObjCBridgeRelated,
+ SourceRange(ObjCBridgeRelatedLoc, T.getCloseLocation()),
+ ScopeName, ScopeLoc,
+ RelatedClass,
+ ClassMethod,
+ InstanceMethod,
+ Syntax);
+}
// Late Parsed Attributes:
// See other examples of late parsing in lib/Parse/ParseCXXInlineMethods
@@ -1038,13 +1081,6 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
// Consume the previously pushed token.
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
- if (OnDefinition && !IsThreadSafetyAttribute(LA.AttrName.getName())) {
- // FIXME: Do not warn on C++11 attributes, once we start supporting
- // them here.
- Diag(Tok, diag::warn_attribute_on_function_definition)
- << LA.AttrName.getName();
- }
-
ParsedAttributes Attrs(AttrFactory);
SourceLocation endLoc;
@@ -1071,7 +1107,8 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
Actions.ActOnReenterFunctionContext(Actions.CurScope, D);
ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc,
- 0, SourceLocation(), AttributeList::AS_GNU);
+ nullptr, SourceLocation(), AttributeList::AS_GNU,
+ nullptr);
if (HasFunScope) {
Actions.ActOnExitFunctionContext();
@@ -1084,15 +1121,21 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
// If there are multiple decls, then the decl cannot be within the
// function scope.
ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc,
- 0, SourceLocation(), AttributeList::AS_GNU);
+ nullptr, SourceLocation(), AttributeList::AS_GNU,
+ nullptr);
}
} else {
Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName();
}
- for (unsigned i = 0, ni = LA.Decls.size(); i < ni; ++i) {
+ const AttributeList *AL = Attrs.getList();
+ if (OnDefinition && AL && !AL->isCXX11Attribute() &&
+ AL->isKnownToGCC())
+ Diag(Tok, diag::warn_attribute_on_function_definition)
+ << &LA.AttrName;
+
+ for (unsigned i = 0, ni = LA.Decls.size(); i < ni; ++i)
Actions.ActOnFinishDelayedAttribute(getCurScope(), LA.Decls[i], Attrs);
- }
if (Tok.getLocation() != OrigLoc) {
// Due to a parsing error, we either went over the cached tokens or
@@ -1106,101 +1149,29 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
}
}
-/// \brief Wrapper around a case statement checking if AttrName is
-/// one of the thread safety attributes
-bool Parser::IsThreadSafetyAttribute(StringRef AttrName) {
- return llvm::StringSwitch<bool>(AttrName)
- .Case("guarded_by", true)
- .Case("guarded_var", true)
- .Case("pt_guarded_by", true)
- .Case("pt_guarded_var", true)
- .Case("lockable", true)
- .Case("scoped_lockable", true)
- .Case("no_thread_safety_analysis", true)
- .Case("acquired_after", true)
- .Case("acquired_before", true)
- .Case("exclusive_lock_function", true)
- .Case("shared_lock_function", true)
- .Case("exclusive_trylock_function", true)
- .Case("shared_trylock_function", true)
- .Case("unlock_function", true)
- .Case("lock_returned", true)
- .Case("locks_excluded", true)
- .Case("exclusive_locks_required", true)
- .Case("shared_locks_required", true)
- .Default(false);
-}
-
-/// \brief Parse the contents of thread safety attributes. These
-/// should always be parsed as an expression list.
-///
-/// We need to special case the parsing due to the fact that if the first token
-/// of the first argument is an identifier, the main parse loop will store
-/// that token as a "parameter" and the rest of
-/// the arguments will be added to a list of "arguments". However,
-/// subsequent tokens in the first argument are lost. We instead parse each
-/// argument as an expression and add all arguments to the list of "arguments".
-/// In future, we will take advantage of this special case to also
-/// deal with some argument scoping issues here (for example, referring to a
-/// function parameter in the attribute on that function).
-void Parser::ParseThreadSafetyAttribute(IdentifierInfo &AttrName,
- SourceLocation AttrNameLoc,
- ParsedAttributes &Attrs,
- SourceLocation *EndLoc) {
- assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
-
- BalancedDelimiterTracker T(*this, tok::l_paren);
- T.consumeOpen();
-
- ArgsVector ArgExprs;
- bool ArgExprsOk = true;
-
- // now parse the list of expressions
- while (Tok.isNot(tok::r_paren)) {
- EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
- ExprResult ArgExpr(ParseAssignmentExpression());
- if (ArgExpr.isInvalid()) {
- ArgExprsOk = false;
- T.consumeClose();
- break;
- } else {
- ArgExprs.push_back(ArgExpr.release());
- }
- if (Tok.isNot(tok::comma))
- break;
- ConsumeToken(); // Eat the comma, move to the next argument
- }
- // Match the ')'.
- if (ArgExprsOk && !T.consumeClose()) {
- Attrs.addNew(&AttrName, AttrNameLoc, 0, AttrNameLoc, ArgExprs.data(),
- ArgExprs.size(), AttributeList::AS_GNU);
- }
- if (EndLoc)
- *EndLoc = T.getCloseLocation();
-}
-
void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs,
- SourceLocation *EndLoc) {
+ SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc,
+ AttributeList::Syntax Syntax) {
assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
T.skipToEnd();
return;
}
IdentifierLoc *ArgumentKind = ParseIdentifierLoc();
- if (Tok.isNot(tok::comma)) {
- Diag(Tok, diag::err_expected_comma);
+ if (ExpectAndConsume(tok::comma)) {
T.skipToEnd();
return;
}
- ConsumeToken();
SourceRange MatchingCTypeRange;
TypeResult MatchingCType = ParseTypeName(&MatchingCTypeRange);
@@ -1211,10 +1182,9 @@ void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
bool LayoutCompatible = false;
bool MustBeNull = false;
- while (Tok.is(tok::comma)) {
- ConsumeToken();
+ while (TryConsumeToken(tok::comma)) {
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
T.skipToEnd();
return;
}
@@ -1232,10 +1202,9 @@ void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
}
if (!T.consumeClose()) {
- Attrs.addNewTypeTagForDatatype(&AttrName, AttrNameLoc, 0, AttrNameLoc,
- ArgumentKind, MatchingCType.release(),
- LayoutCompatible, MustBeNull,
- AttributeList::AS_GNU);
+ Attrs.addNewTypeTagForDatatype(&AttrName, AttrNameLoc, ScopeName, ScopeLoc,
+ ArgumentKind, MatchingCType.get(),
+ LayoutCompatible, MustBeNull, Syntax);
}
if (EndLoc)
@@ -1337,8 +1306,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts,
// parsing c none objective-c decls.
ObjCDeclContextSwitch ObjCDC(*this);
- Decl *SingleDecl = 0;
- Decl *OwnedType = 0;
+ Decl *SingleDecl = nullptr;
+ Decl *OwnedType = nullptr;
switch (Tok.getKind()) {
case tok::kw_template:
case tok::kw_export:
@@ -1508,8 +1477,7 @@ void Parser::SkipMalformedDecl() {
// This declaration isn't over yet. Keep skipping.
continue;
}
- if (Tok.is(tok::semi))
- ConsumeToken();
+ TryConsumeToken(tok::semi);
return;
case tok::l_square:
@@ -1562,6 +1530,9 @@ void Parser::SkipMalformedDecl() {
break;
case tok::eof:
+ case tok::annot_module_begin:
+ case tok::annot_module_end:
+ case tok::annot_module_include:
return;
default:
@@ -1632,7 +1603,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
} else {
if (Tok.is(tok::l_brace)) {
Diag(Tok, diag::err_function_definition_not_allowed);
- SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
+ SkipMalformedDecl();
+ return DeclGroupPtrTy();
}
}
}
@@ -1648,9 +1620,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
// don't need to parse the container in advance.
if (FRI && (Tok.is(tok::colon) || isTokIdentifier_in())) {
bool IsForRangeLoop = false;
- if (Tok.is(tok::colon)) {
+ if (TryConsumeToken(tok::colon, FRI->ColonLoc)) {
IsForRangeLoop = true;
- FRI->ColonLoc = ConsumeToken();
if (Tok.is(tok::l_brace))
FRI->RangeExpr = ParseBraceInitializer();
else
@@ -1666,7 +1637,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
}
SmallVector<Decl *, 8> DeclsInGroup;
- Decl *FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes(D);
+ Decl *FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes(
+ D, ParsedTemplateInfo(), FRI);
if (LateParsedAttrs.size() > 0)
ParseLexedAttributeList(LateParsedAttrs, FirstDecl, true, false);
D.complete(FirstDecl);
@@ -1677,9 +1649,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
// If we don't have a comma, it is either the end of the list (a ';') or an
// error, bail out.
- while (Tok.is(tok::comma)) {
- SourceLocation CommaLoc = ConsumeToken();
-
+ SourceLocation CommaLoc;
+ while (TryConsumeToken(tok::comma, CommaLoc)) {
if (Tok.isAtStartOfLine() && ExpectSemi && !MightBeDeclarator(Context)) {
// This comma was followed by a line-break and something which can't be
// the start of a declarator. The comma was probably a typo for a
@@ -1724,8 +1695,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
// Otherwise things are very confused and we skip to recover.
if (!isDeclarationSpecifier()) {
SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
- if (Tok.is(tok::semi))
- ConsumeToken();
+ TryConsumeToken(tok::semi);
}
}
@@ -1744,7 +1714,7 @@ bool Parser::ParseAsmAttributesAfterDeclarator(Declarator &D) {
return true;
}
- D.setAsmLabel(AsmLabel.release());
+ D.setAsmLabel(AsmLabel.get());
D.SetRangeEnd(Loc);
}
@@ -1774,18 +1744,18 @@ bool Parser::ParseAsmAttributesAfterDeclarator(Declarator &D) {
/// According to the standard grammar, =default and =delete are function
/// definitions, but that definitely doesn't fit with the parser here.
///
-Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D,
- const ParsedTemplateInfo &TemplateInfo) {
+Decl *Parser::ParseDeclarationAfterDeclarator(
+ Declarator &D, const ParsedTemplateInfo &TemplateInfo) {
if (ParseAsmAttributesAfterDeclarator(D))
- return 0;
+ return nullptr;
return ParseDeclarationAfterDeclaratorAndAttributes(D, TemplateInfo);
}
-Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
- const ParsedTemplateInfo &TemplateInfo) {
+Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
+ Declarator &D, const ParsedTemplateInfo &TemplateInfo, ForRangeInit *FRI) {
// Inform the current actions module that we just parsed this declarator.
- Decl *ThisDecl = 0;
+ Decl *ThisDecl = nullptr;
switch (TemplateInfo.Kind) {
case ParsedTemplateInfo::NonTemplate:
ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
@@ -1808,7 +1778,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, D);
if (ThisRes.isInvalid()) {
SkipUntil(tok::semi, StopBeforeMatch);
- return 0;
+ return nullptr;
}
ThisDecl = ThisRes.get();
} else {
@@ -1832,8 +1802,8 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
// Recover as if it were an explicit specialization.
TemplateParameterLists FakedParamLists;
FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
- 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, 0, 0,
- LAngleLoc));
+ 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, nullptr,
+ 0, LAngleLoc));
ThisDecl =
Actions.ActOnTemplateDeclarator(getCurScope(), FakedParamLists, D);
@@ -1848,7 +1818,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
// Parse declarator '=' initializer.
// If a '==' or '+=' is found, suggest a fixit to '='.
if (isTokenEqualOrEqualTypo()) {
- ConsumeToken();
+ SourceLocation EqualLoc = ConsumeToken();
if (Tok.is(tok::kw_delete)) {
if (D.isFunctionDeclarator())
@@ -1872,21 +1842,37 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
Actions.CodeCompleteInitializer(getCurScope(), ThisDecl);
Actions.FinalizeDeclaration(ThisDecl);
cutOffParsing();
- return 0;
+ return nullptr;
}
ExprResult Init(ParseInitializer());
+ // If this is the only decl in (possibly) range based for statement,
+ // our best guess is that the user meant ':' instead of '='.
+ if (Tok.is(tok::r_paren) && FRI && D.isFirstDeclarator()) {
+ Diag(EqualLoc, diag::err_single_decl_assign_in_for_range)
+ << FixItHint::CreateReplacement(EqualLoc, ":");
+ // We are trying to stop parser from looking for ';' in this for
+ // statement, therefore preventing spurious errors to be issued.
+ FRI->ColonLoc = EqualLoc;
+ Init = ExprError();
+ FRI->RangeExpr = Init;
+ }
+
if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {
Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);
ExitScope();
}
if (Init.isInvalid()) {
- SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
+ SmallVector<tok::TokenKind, 2> StopTokens;
+ StopTokens.push_back(tok::comma);
+ if (D.getContext() == Declarator::ForContext)
+ StopTokens.push_back(tok::r_paren);
+ SkipUntil(StopTokens, StopAtSemi | StopBeforeMatch);
Actions.ActOnInitializerError(ThisDecl);
} else
- Actions.AddInitializerToDecl(ThisDecl, Init.take(),
+ Actions.AddInitializerToDecl(ThisDecl, Init.get(),
/*DirectInit=*/false, TypeContainsAuto);
}
} else if (Tok.is(tok::l_paren)) {
@@ -1925,7 +1911,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
ExprResult Initializer = Actions.ActOnParenListExpr(T.getOpenLocation(),
T.getCloseLocation(),
Exprs);
- Actions.AddInitializerToDecl(ThisDecl, Initializer.take(),
+ Actions.AddInitializerToDecl(ThisDecl, Initializer.get(),
/*DirectInit=*/true, TypeContainsAuto);
}
} else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace) &&
@@ -1948,7 +1934,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
if (Init.isInvalid()) {
Actions.ActOnInitializerError(ThisDecl);
} else
- Actions.AddInitializerToDecl(ThisDecl, Init.take(),
+ Actions.AddInitializerToDecl(ThisDecl, Init.get(),
/*DirectInit=*/true, TypeContainsAuto);
} else {
@@ -1975,8 +1961,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS,
// Validate declspec for type-name.
unsigned Specs = DS.getParsedSpecifiers();
- if ((DSC == DSC_type_specifier || DSC == DSC_trailing) &&
- !DS.hasTypeSpecifier()) {
+ if (isTypeSpecifier(DSC) && !DS.hasTypeSpecifier()) {
Diag(Tok, diag::err_expected_type);
DS.SetTypeSpecError();
} else if (Specs == DeclSpec::PQ_None && !DS.getNumProtocolQualifiers() &&
@@ -2050,7 +2035,7 @@ static bool isValidAfterIdentifierInDeclarator(const Token &T) {
///
bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
const ParsedTemplateInfo &TemplateInfo,
- AccessSpecifier AS, DeclSpecContext DSC,
+ AccessSpecifier AS, DeclSpecContext DSC,
ParsedAttributesWithRange &Attrs) {
assert(Tok.is(tok::identifier) && "should have identifier");
@@ -2074,8 +2059,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
// within a type specifier. Outside of C++, we allow this even if the
// language doesn't "officially" support implicit int -- we support
// implicit int as an extension in C99 and C11.
- if (DSC != DSC_type_specifier && DSC != DSC_trailing &&
- !getLangOpts().CPlusPlus &&
+ if (!isTypeSpecifier(DSC) && !getLangOpts().CPlusPlus &&
isValidAfterIdentifierInDeclarator(NextToken())) {
// If this token is valid for implicit int, e.g. "static x = 4", then
// we just avoid eating the identifier, so it will be parsed as the
@@ -2098,8 +2082,8 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
// This is a common problem in C (saying 'foo' instead of 'struct foo').
//
// C++ doesn't need this, and isTagName doesn't take SS.
- if (SS == 0) {
- const char *TagName = 0, *FixitTagName = 0;
+ if (SS == nullptr) {
+ const char *TagName = nullptr, *FixitTagName = nullptr;
tok::TokenKind TagKind = tok::unknown;
switch (Actions.isTagName(*Tok.getIdentifierInfo(), getCurScope())) {
@@ -2145,7 +2129,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
// Determine whether this identifier could plausibly be the name of something
// being declared (with a missing type).
- if (DSC != DSC_type_specifier && DSC != DSC_trailing &&
+ if (!isTypeSpecifier(DSC) &&
(!SS || DSC == DSC_top_level || DSC == DSC_class)) {
// Look ahead to the next token to try to figure out what this declaration
// was supposed to be.
@@ -2155,15 +2139,14 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
// x(int n); // 'x' is not a type
// x (*p)[]; // 'x' is a type
//
- // Since we're in an error case (or the rare 'implicit int in C++' MS
- // extension), we can afford to perform a tentative parse to determine
- // which case we're in.
+ // Since we're in an error case, we can afford to perform a tentative
+ // parse to determine which case we're in.
TentativeParsingAction PA(*this);
ConsumeToken();
TPResult TPR = TryParseDeclarator(/*mayBeAbstract*/false);
PA.Revert();
- if (TPR != TPResult::False()) {
+ if (TPR != TPResult::False) {
// The identifier is followed by a parenthesized declarator.
// It's supposed to be a type.
break;
@@ -2202,39 +2185,33 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
}
}
- // This is almost certainly an invalid type name. Let the action emit a
- // diagnostic and attempt to recover.
+ // This is almost certainly an invalid type name. Let Sema emit a diagnostic
+ // and attempt to recover.
ParsedType T;
IdentifierInfo *II = Tok.getIdentifierInfo();
- if (Actions.DiagnoseUnknownTypeName(II, Loc, getCurScope(), SS, T)) {
- // The action emitted a diagnostic, so we don't have to.
- if (T) {
- // The action has suggested that the type T could be used. Set that as
- // the type in the declaration specifiers, consume the would-be type
- // name token, and we're done.
- const char *PrevSpec;
- unsigned DiagID;
- DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T);
- DS.SetRangeEnd(Tok.getLocation());
- ConsumeToken();
- // There may be other declaration specifiers after this.
- return true;
- } else if (II != Tok.getIdentifierInfo()) {
- // If no type was suggested, the correction is to a keyword
- Tok.setKind(II->getTokenID());
- // There may be other declaration specifiers after this.
- return true;
- }
-
- // Fall through; the action had no suggestion for us.
- } else {
- // The action did not emit a diagnostic, so emit one now.
- SourceRange R;
- if (SS) R = SS->getRange();
- Diag(Loc, diag::err_unknown_typename) << Tok.getIdentifierInfo() << R;
+ Actions.DiagnoseUnknownTypeName(II, Loc, getCurScope(), SS, T,
+ getLangOpts().CPlusPlus &&
+ NextToken().is(tok::less));
+ if (T) {
+ // The action has suggested that the type T could be used. Set that as
+ // the type in the declaration specifiers, consume the would-be type
+ // name token, and we're done.
+ const char *PrevSpec;
+ unsigned DiagID;
+ DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T,
+ Actions.getASTContext().getPrintingPolicy());
+ DS.SetRangeEnd(Tok.getLocation());
+ ConsumeToken();
+ // There may be other declaration specifiers after this.
+ return true;
+ } else if (II != Tok.getIdentifierInfo()) {
+ // If no type was suggested, the correction is to a keyword
+ Tok.setKind(II->getTokenID());
+ // There may be other declaration specifiers after this.
+ return true;
}
- // Mark this as an error.
+ // Otherwise, the action had no suggestion for us. Mark this as an error.
DS.SetTypeSpecError();
DS.SetRangeEnd(Tok.getLocation());
ConsumeToken();
@@ -2256,8 +2233,13 @@ Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) {
return DSC_class;
if (Context == Declarator::FileContext)
return DSC_top_level;
+ if (Context == Declarator::TemplateTypeArgContext)
+ return DSC_template_type_arg;
if (Context == Declarator::TrailingReturnContext)
return DSC_trailing;
+ if (Context == Declarator::AliasDeclContext ||
+ Context == Declarator::AliasTemplateContext)
+ return DSC_alias_declaration;
return DSC_normal;
}
@@ -2282,8 +2264,8 @@ ExprResult Parser::ParseAlignArgument(SourceLocation Start,
} else
ER = ParseConstantExpression();
- if (getLangOpts().CPlusPlus11 && Tok.is(tok::ellipsis))
- EllipsisLoc = ConsumeToken();
+ if (getLangOpts().CPlusPlus11)
+ TryConsumeToken(tok::ellipsis, EllipsisLoc);
return ER;
}
@@ -2305,7 +2287,7 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
SourceLocation KWLoc = ConsumeToken();
BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen))
+ if (T.expectAndConsume())
return;
SourceLocation EllipsisLoc;
@@ -2320,8 +2302,8 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
*EndLoc = T.getCloseLocation();
ArgsVector ArgExprs;
- ArgExprs.push_back(ArgExpr.release());
- Attrs.addNew(KWName, KWLoc, 0, KWLoc, ArgExprs.data(), 1,
+ ArgExprs.push_back(ArgExpr.get());
+ Attrs.addNew(KWName, KWLoc, nullptr, KWLoc, ArgExprs.data(), 1,
AttributeList::AS_Keyword, EllipsisLoc);
}
@@ -2339,7 +2321,6 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
assert(DS.hasTagDefinition() && "shouldn't call this");
bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level);
- bool HasMissingSemi = false;
if (getLangOpts().CPlusPlus &&
(Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
@@ -2349,63 +2330,77 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
return true;
}
+ bool HasScope = Tok.is(tok::annot_cxxscope);
+ // Make a copy in case GetLookAheadToken invalidates the result of NextToken.
+ Token AfterScope = HasScope ? NextToken() : Tok;
+
// Determine whether the following tokens could possibly be a
// declarator.
- if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) {
- const Token &Next = NextToken();
+ bool MightBeDeclarator = true;
+ if (Tok.is(tok::kw_typename) || Tok.is(tok::annot_typename)) {
+ // A declarator-id can't start with 'typename'.
+ MightBeDeclarator = false;
+ } else if (AfterScope.is(tok::annot_template_id)) {
+ // If we have a type expressed as a template-id, this cannot be a
+ // declarator-id (such a type cannot be redeclared in a simple-declaration).
+ TemplateIdAnnotation *Annot =
+ static_cast<TemplateIdAnnotation *>(AfterScope.getAnnotationValue());
+ if (Annot->Kind == TNK_Type_template)
+ MightBeDeclarator = false;
+ } else if (AfterScope.is(tok::identifier)) {
+ const Token &Next = HasScope ? GetLookAheadToken(2) : NextToken();
+
// These tokens cannot come after the declarator-id in a
// simple-declaration, and are likely to come after a type-specifier.
- HasMissingSemi = 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);
- } else if (Tok.is(tok::annot_cxxscope) &&
- NextToken().is(tok::identifier) &&
- DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
- // We almost certainly have a missing semicolon. Look up the name and
- // check; if it names a type, we're missing a semicolon.
- CXXScopeSpec SS;
- Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
- Tok.getAnnotationRange(), SS);
- const Token &Next = NextToken();
- IdentifierInfo *Name = Next.getIdentifierInfo();
- Sema::NameClassification Classification =
- Actions.ClassifyName(getCurScope(), SS, Name, Next.getLocation(),
- NextToken(), /*IsAddressOfOperand*/false);
- switch (Classification.getKind()) {
- case Sema::NC_Error:
- SkipMalformedDecl();
- return true;
+ 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)) {
+ // Missing a semicolon.
+ MightBeDeclarator = false;
+ } else if (HasScope) {
+ // If the declarator-id has a scope specifier, it must redeclare a
+ // previously-declared entity. If that's a type (and this is not a
+ // typedef), that's an error.
+ CXXScopeSpec SS;
+ Actions.RestoreNestedNameSpecifierAnnotation(
+ Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS);
+ IdentifierInfo *Name = AfterScope.getIdentifierInfo();
+ Sema::NameClassification Classification = Actions.ClassifyName(
+ getCurScope(), SS, Name, AfterScope.getLocation(), Next,
+ /*IsAddressOfOperand*/false);
+ switch (Classification.getKind()) {
+ case Sema::NC_Error:
+ SkipMalformedDecl();
+ return true;
- case Sema::NC_Keyword:
- case Sema::NC_NestedNameSpecifier:
- llvm_unreachable("typo correction and nested name specifiers not "
- "possible here");
+ case Sema::NC_Keyword:
+ case Sema::NC_NestedNameSpecifier:
+ llvm_unreachable("typo correction and nested name specifiers not "
+ "possible here");
- case Sema::NC_Type:
- case Sema::NC_TypeTemplate:
- // Not a previously-declared non-type entity.
- HasMissingSemi = true;
- break;
+ case Sema::NC_Type:
+ case Sema::NC_TypeTemplate:
+ // Not a previously-declared non-type entity.
+ MightBeDeclarator = false;
+ break;
- case Sema::NC_Unknown:
- case Sema::NC_Expression:
- case Sema::NC_VarTemplate:
- case Sema::NC_FunctionTemplate:
- // Might be a redeclaration of a prior entity.
- HasMissingSemi = false;
- break;
+ case Sema::NC_Unknown:
+ case Sema::NC_Expression:
+ case Sema::NC_VarTemplate:
+ case Sema::NC_FunctionTemplate:
+ // Might be a redeclaration of a prior entity.
+ break;
+ }
}
- } else if (Tok.is(tok::kw_typename) || Tok.is(tok::annot_typename)) {
- HasMissingSemi = true;
}
- if (!HasMissingSemi)
+ if (MightBeDeclarator)
return false;
+ const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();
Diag(PP.getLocForEndOfToken(DS.getRepAsDecl()->getLocEnd()),
- diag::err_expected_semi_after_tagdecl)
- << DeclSpec::getSpecifierName(DS.getTypeSpecType());
+ diag::err_expected_after)
+ << DeclSpec::getSpecifierName(DS.getTypeSpecType(), PPol) << tok::semi;
// Try to recover from the typo, by dropping the tag definition and parsing
// the problematic tokens as a type.
@@ -2461,9 +2456,10 @@ 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();
while (1) {
bool isInvalid = false;
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID = 0;
SourceLocation Loc = Tok.getLocation();
@@ -2484,7 +2480,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// If this is not a declaration specifier token, we're done reading decl
// specifiers. First verify that DeclSpec's are consistent.
- DS.Finish(Diags, PP);
+ DS.Finish(Diags, PP, Policy);
return;
case tok::l_square:
@@ -2586,7 +2582,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if ((DSContext == DSC_top_level || DSContext == DSC_class) &&
TemplateId->Name &&
Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS)) {
- if (isConstructorDeclarator()) {
+ if (isConstructorDeclarator(/*Unqualified*/false)) {
// The user meant this to be an out-of-line constructor
// definition, but template arguments are not allowed
// there. Just allow this as a constructor; we'll
@@ -2618,7 +2614,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
ParsedType T = getTypeAnnotation(Tok);
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename,
Tok.getAnnotationEndLoc(),
- PrevSpec, DiagID, T);
+ PrevSpec, DiagID, T, Policy);
if (isInvalid)
break;
}
@@ -2636,7 +2632,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if ((DSContext == DSC_top_level || DSContext == DSC_class) &&
Actions.isCurrentClassName(*Next.getIdentifierInfo(), getCurScope(),
&SS)) {
- if (isConstructorDeclarator())
+ if (isConstructorDeclarator(/*Unqualified*/false))
goto DoneWithDeclSpec;
// As noted in C++ [class.qual]p2 (cited above), when the name
@@ -2677,7 +2673,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
ConsumeToken(); // The C++ scope.
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
- DiagID, TypeRep);
+ DiagID, TypeRep, Policy);
if (isInvalid)
break;
@@ -2696,7 +2692,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if (Tok.getAnnotationValue()) {
ParsedType T = getTypeAnnotation(Tok);
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
- DiagID, T);
+ DiagID, T, Policy);
} else
DS.SetTypeSpecError();
@@ -2734,24 +2730,23 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// typedef-name
case tok::kw_decltype:
case tok::identifier: {
+ // This identifier can only be a typedef name if we haven't already seen
+ // a type-specifier. Without this check we misparse:
+ // typedef int X; struct Y { short X; }; as 'short int'.
+ if (DS.hasTypeSpecifier())
+ goto DoneWithDeclSpec;
+
// In C++, check to see if this is a scope specifier like foo::bar::, if
// so handle it as such. This is important for ctor parsing.
if (getLangOpts().CPlusPlus) {
if (TryAnnotateCXXScopeToken(EnteringContext)) {
- if (!DS.hasTypeSpecifier())
- DS.SetTypeSpecError();
+ DS.SetTypeSpecError();
goto DoneWithDeclSpec;
}
if (!Tok.is(tok::identifier))
continue;
}
- // This identifier can only be a typedef name if we haven't already seen
- // a type-specifier. Without this check we misparse:
- // typedef int X; struct Y { short X; }; as 'short int'.
- if (DS.hasTypeSpecifier())
- goto DoneWithDeclSpec;
-
// Check for need to substitute AltiVec keyword tokens.
if (TryAltiVecToken(DS, Loc, PrevSpec, DiagID, isInvalid))
break;
@@ -2765,11 +2760,21 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
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.
+ if (!TypeRep && DSContext == DSC_template_type_arg &&
+ getLangOpts().MSVCCompat && getCurScope()->isTemplateParamScope()) {
+ TypeRep = Actions.ActOnDelayedDefaultTemplateArg(
+ *Tok.getIdentifierInfo(), Tok.getLocation());
+ }
+
// If this is not a typedef name, don't parse it as part of the declspec,
// it must be an implicit int or an error.
if (!TypeRep) {
ParsedAttributesWithRange Attrs(AttrFactory);
- if (ParseImplicitInt(DS, 0, TemplateInfo, AS, DSContext, Attrs)) {
+ if (ParseImplicitInt(DS, nullptr, TemplateInfo, AS, DSContext, Attrs)) {
if (!Attrs.empty()) {
AttrsLastTime = true;
attrs.takeAllFrom(Attrs);
@@ -2783,11 +2788,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// check whether this is a constructor declaration.
if (getLangOpts().CPlusPlus && DSContext == DSC_class &&
Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) &&
- isConstructorDeclarator())
+ isConstructorDeclarator(/*Unqualified*/true))
goto DoneWithDeclSpec;
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
- DiagID, TypeRep);
+ DiagID, TypeRep, Policy);
if (isInvalid)
break;
@@ -2819,7 +2824,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// constructor declaration.
if (getLangOpts().CPlusPlus && DSContext == DSC_class &&
Actions.isCurrentClassName(*TemplateId->Name, getCurScope()) &&
- isConstructorDeclarator())
+ isConstructorDeclarator(TemplateId->SS.isEmpty()))
goto DoneWithDeclSpec;
// Turn the template-id annotation token into a type annotation
@@ -2830,7 +2835,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// GNU attributes support.
case tok::kw___attribute:
- ParseGNUAttributes(DS.getAttributes(), 0, LateAttrs);
+ ParseGNUAttributes(DS.getAttributes(), nullptr, LateAttrs);
continue;
// Microsoft declspec support.
@@ -2843,10 +2848,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
isInvalid = DS.setFunctionSpecForceInline(Loc, PrevSpec, DiagID);
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = Tok.getLocation();
- // FIXME: This does not work correctly if it is set to be a declspec
- // attribute, and a GNU attribute is simply incorrect.
- DS.getAttributes().addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
- AttributeList::AS_GNU);
+ DS.getAttributes().addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc,
+ nullptr, 0, AttributeList::AS_Keyword);
break;
}
@@ -2876,46 +2879,46 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// storage-class-specifier
case tok::kw_typedef:
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_typedef, Loc,
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
break;
case tok::kw_extern:
if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread)
Diag(Tok, diag::ext_thread_before) << "extern";
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_extern, Loc,
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
break;
case tok::kw___private_extern__:
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_private_extern,
- Loc, PrevSpec, DiagID);
+ Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_static:
if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread)
Diag(Tok, diag::ext_thread_before) << "static";
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_static, Loc,
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11) {
if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
if (!isInvalid)
Diag(Tok, diag::ext_auto_storage_class)
<< FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
} else
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
} else
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
break;
case tok::kw_register:
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc,
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
break;
case tok::kw_mutable:
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_mutable, Loc,
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
break;
case tok::kw___thread:
isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS___thread, Loc,
@@ -2977,19 +2980,19 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// type-specifier
case tok::kw_short:
isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_long:
if (DS.getTypeSpecWidth() != DeclSpec::TSW_long)
isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
else
isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw___int64:
isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_signed:
isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec,
@@ -3009,43 +3012,43 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
break;
case tok::kw_void:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_char:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_int:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw___int128:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_half:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_float:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_double:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_wchar_t:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_char16_t:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_char32_t:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_bool:
case tok::kw__Bool:
@@ -3059,62 +3062,30 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
isInvalid = true;
} else {
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
}
break;
case tok::kw__Decimal32:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw__Decimal64:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw__Decimal128:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw___vector:
- isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
+ isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw___pixel:
- isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID);
- break;
- case tok::kw_image1d_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image1d_t, Loc,
- PrevSpec, DiagID);
- break;
- case tok::kw_image1d_array_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image1d_array_t, Loc,
- PrevSpec, DiagID);
- break;
- case tok::kw_image1d_buffer_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image1d_buffer_t, Loc,
- PrevSpec, DiagID);
- break;
- case tok::kw_image2d_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image2d_t, Loc,
- PrevSpec, DiagID);
- break;
- case tok::kw_image2d_array_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image2d_array_t, Loc,
- PrevSpec, DiagID);
- break;
- case tok::kw_image3d_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image3d_t, Loc,
- PrevSpec, DiagID);
- break;
- case tok::kw_sampler_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_sampler_t, Loc,
- PrevSpec, DiagID);
- break;
- case tok::kw_event_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_event_t, Loc,
- PrevSpec, DiagID);
+ isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw___unknown_anytype:
isInvalid = DS.SetTypeSpecType(TST_unknown_anytype, Loc,
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
break;
// class-specifier:
@@ -3198,9 +3169,6 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
break;
// OpenCL qualifiers:
- case tok::kw_private:
- if (!getLangOpts().OpenCL)
- goto DoneWithDeclSpec;
case tok::kw___private:
case tok::kw___global:
case tok::kw___local:
@@ -3208,7 +3176,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
case tok::kw___read_only:
case tok::kw___write_only:
case tok::kw___read_write:
- ParseOpenCLQualifiers(DS);
+ ParseOpenCLQualifiers(DS.getAttributes());
break;
case tok::less:
@@ -3305,13 +3273,12 @@ ParseStructDeclaration(ParsingDeclSpec &DS, FieldCallback &Fields) {
ParseDeclarator(DeclaratorInfo.D);
}
- if (Tok.is(tok::colon)) {
- ConsumeToken();
+ if (TryConsumeToken(tok::colon)) {
ExprResult Res(ParseConstantExpression());
if (Res.isInvalid())
SkipUntil(tok::semi, StopBeforeMatch);
else
- DeclaratorInfo.BitfieldSize = Res.release();
+ DeclaratorInfo.BitfieldSize = Res.get();
}
// If attributes exist after the declarator, parse them.
@@ -3322,12 +3289,9 @@ ParseStructDeclaration(ParsingDeclSpec &DS, FieldCallback &Fields) {
// If we don't have a comma, it is either the end of the list (a ';')
// or an error, bail out.
- if (Tok.isNot(tok::comma))
+ if (!TryConsumeToken(tok::comma, CommaLoc))
return;
- // Consume the comma.
- CommaLoc = ConsumeToken();
-
FirstDeclarator = false;
}
}
@@ -3358,7 +3322,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
SmallVector<Decl *, 32> FieldDecls;
// While we still have something to read, read the declarations in the struct.
- while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
// Each iteration of this loop reads one struct-declaration.
// Check for extraneous top-level semicolon.
@@ -3394,7 +3358,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
SmallVectorImpl<Decl *> &FieldDecls) :
P(P), TagDecl(TagDecl), FieldDecls(FieldDecls) {}
- void invoke(ParsingFieldDeclarator &FD) {
+ void invoke(ParsingFieldDeclarator &FD) override {
// Install the declarator into the current TagDecl.
Decl *Field = P.Actions.ActOnField(P.getCurScope(), TagDecl,
FD.D.getDeclSpec().getSourceRange().getBegin(),
@@ -3415,9 +3379,9 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
continue;
}
ConsumeToken();
- ExpectAndConsume(tok::l_paren, diag::err_expected_lparen);
+ ExpectAndConsume(tok::l_paren);
if (!Tok.is(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::semi);
continue;
}
@@ -3426,21 +3390,22 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
Tok.getIdentifierInfo(), Fields);
FieldDecls.insert(FieldDecls.end(), Fields.begin(), Fields.end());
ConsumeToken();
- ExpectAndConsume(tok::r_paren, diag::err_expected_rparen);
+ ExpectAndConsume(tok::r_paren);
}
- if (Tok.is(tok::semi)) {
- ConsumeToken();
- } else if (Tok.is(tok::r_brace)) {
+ if (TryConsumeToken(tok::semi))
+ continue;
+
+ if (Tok.is(tok::r_brace)) {
ExpectAndConsume(tok::semi, diag::ext_expected_semi_decl_list);
break;
- } else {
- ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list);
- // Skip to end of block or statement to avoid ext-warning on extra ';'.
- SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
- // If we stopped at a ';', eat it.
- if (Tok.is(tok::semi)) ConsumeToken();
}
+
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list);
+ // Skip to end of block or statement to avoid ext-warning on extra ';'.
+ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
+ // If we stopped at a ';', eat it.
+ TryConsumeToken(tok::semi);
}
T.consumeClose();
@@ -3557,7 +3522,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
return;
if (SS.isSet() && Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
if (Tok.isNot(tok::l_brace)) {
// Has no name and is not a definition.
// Skip the rest of this declarator, up until the comma or semicolon.
@@ -3570,7 +3535,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
// Must have either 'enum name' or 'enum {...}'.
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace) &&
!(AllowFixedUnderlyingType && Tok.is(tok::colon))) {
- Diag(Tok, diag::err_expected_ident_lbrace);
+ Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace;
// Skip the rest of this declarator, up until the comma or semicolon.
SkipUntil(tok::comma, StopAtSemi);
@@ -3578,7 +3543,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
}
// If an identifier is present, consume and remember it.
- IdentifierInfo *Name = 0;
+ IdentifierInfo *Name = nullptr;
SourceLocation NameLoc;
if (Tok.is(tok::identifier)) {
Name = Tok.getIdentifierInfo();
@@ -3617,13 +3582,13 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
TPResult TPR = isExpressionOrTypeSpecifierSimple(NextToken().getKind());
// If the next token starts an expression, we know we're parsing a
// bit-field. This is the common case.
- if (TPR == TPResult::True())
+ if (TPR == TPResult::True)
PossibleBitfield = true;
// If the next token starts a type-specifier-seq, it may be either a
// a fixed underlying type or the start of a function-style cast in C++;
// lookahead one more token to see if it's obvious that we have a
// fixed underlying type.
- else if (TPR == TPResult::False() &&
+ else if (TPR == TPResult::False &&
GetLookAheadToken(2).getKind() == tok::semi) {
// Consume the ':'.
ConsumeToken();
@@ -3643,7 +3608,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
// FIXME: The standard is not entirely clear on how to disambiguate in
// this case.
if ((getLangOpts().CPlusPlus &&
- isCXXDeclarationSpecifier(TPResult::True()) != TPResult::True()) ||
+ isCXXDeclarationSpecifier(TPResult::True) != TPResult::True) ||
(!getLangOpts().CPlusPlus && !isDeclarationSpecifier(true))) {
// We'll parse this as a bitfield later.
PossibleBitfield = true;
@@ -3696,15 +3661,14 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
} else {
TUK = Sema::TUK_Definition;
}
- } else if (DSC != DSC_type_specifier &&
+ } else if (!isTypeSpecifier(DSC) &&
(Tok.is(tok::semi) ||
(Tok.isAtStartOfLine() &&
!isValidAfterTypeSpecifier(CanBeBitfield)))) {
TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration;
if (Tok.isNot(tok::semi)) {
// A semicolon was missing after this declaration. Diagnose and recover.
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
- "enum");
+ ExpectAndConsume(tok::semi, diag::err_expected_after, "enum");
PP.EnterToken(Tok);
Tok.setKind(tok::semi);
}
@@ -3753,13 +3717,14 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
bool Owned = false;
bool IsDependent = false;
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
Decl *TagDecl = Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK,
StartLoc, SS, Name, NameLoc, attrs.getList(),
AS, DS.getModulePrivateSpecLoc(), TParams,
Owned, IsDependent, ScopedEnumKWLoc,
- IsScopedUsingClassTag, BaseType);
+ IsScopedUsingClassTag, BaseType,
+ DSC == DSC_type_specifier);
if (IsDependent) {
// This enum has a dependent nested-name-specifier. Handle it as a
@@ -3770,9 +3735,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
return;
}
- TypeResult Type = Actions.ActOnDependentTag(getCurScope(), DeclSpec::TST_enum,
- TUK, SS, Name, StartLoc,
- NameLoc);
+ TypeResult Type = Actions.ActOnDependentTag(
+ getCurScope(), DeclSpec::TST_enum, TUK, SS, Name, StartLoc, NameLoc);
if (Type.isInvalid()) {
DS.SetTypeSpecError();
return;
@@ -3780,7 +3744,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
if (DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc,
NameLoc.isValid() ? NameLoc : StartLoc,
- PrevSpec, DiagID, Type.get()))
+ PrevSpec, DiagID, Type.get(),
+ Actions.getASTContext().getPrintingPolicy()))
Diag(StartLoc, DiagID) << PrevSpec;
return;
@@ -3803,7 +3768,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,
NameLoc.isValid() ? NameLoc : StartLoc,
- PrevSpec, DiagID, TagDecl, Owned))
+ PrevSpec, DiagID, TagDecl, Owned,
+ Actions.getASTContext().getPrintingPolicy()))
Diag(StartLoc, DiagID) << PrevSpec;
}
@@ -3819,7 +3785,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
///
void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
// Enter the scope of the enum body and start the definition.
- ParseScope EnumScope(this, Scope::DeclScope);
+ ParseScope EnumScope(this, Scope::DeclScope | Scope::EnumScope);
Actions.ActOnTagStartDefinition(getCurScope(), EnumDecl);
BalancedDelimiterTracker T(*this, tok::l_brace);
@@ -3831,10 +3797,19 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
SmallVector<Decl *, 32> EnumConstantDecls;
- Decl *LastEnumConstDecl = 0;
+ Decl *LastEnumConstDecl = nullptr;
// Parse the enumerator-list.
- while (Tok.is(tok::identifier)) {
+ while (Tok.isNot(tok::r_brace)) {
+ // Parse enumerator. If failed, try skipping till the start of the next
+ // enumerator definition.
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
+ if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch) &&
+ TryConsumeToken(tok::comma))
+ continue;
+ break;
+ }
IdentifierInfo *Ident = Tok.getIdentifierInfo();
SourceLocation IdentLoc = ConsumeToken();
@@ -3848,11 +3823,10 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
ExprResult AssignedVal;
ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
- if (Tok.is(tok::equal)) {
- EqualLoc = ConsumeToken();
+ if (TryConsumeToken(tok::equal, EqualLoc)) {
AssignedVal = ParseConstantExpression();
if (AssignedVal.isInvalid())
- SkipUntil(tok::comma, tok::r_brace, StopAtSemi | StopBeforeMatch);
+ SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch);
}
// Install the enumerator constant into EnumDecl.
@@ -3860,7 +3834,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
LastEnumConstDecl,
IdentLoc, Ident,
attrs.getList(), EqualLoc,
- AssignedVal.release());
+ AssignedVal.get());
PD.complete(EnumConstDecl);
EnumConstantDecls.push_back(EnumConstDecl);
@@ -3874,11 +3848,25 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
continue;
}
- if (Tok.isNot(tok::comma))
- break;
- SourceLocation CommaLoc = ConsumeToken();
+ // Emumerator definition must be finished, only comma or r_brace are
+ // allowed here.
+ SourceLocation CommaLoc;
+ if (Tok.isNot(tok::r_brace) && !TryConsumeToken(tok::comma, CommaLoc)) {
+ if (EqualLoc.isValid())
+ Diag(Tok.getLocation(), diag::err_expected_either) << tok::r_brace
+ << tok::comma;
+ else
+ Diag(Tok.getLocation(), diag::err_expected_end_of_enumerator);
+ if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch)) {
+ if (TryConsumeToken(tok::comma, CommaLoc))
+ continue;
+ } else {
+ break;
+ }
+ }
- if (Tok.isNot(tok::identifier)) {
+ // If comma is followed by r_brace, emit appropriate warning.
+ if (Tok.is(tok::r_brace) && CommaLoc.isValid()) {
if (!getLangOpts().C99 && !getLangOpts().CPlusPlus11)
Diag(CommaLoc, getLangOpts().CPlusPlus ?
diag::ext_enumerator_list_comma_cxx :
@@ -3887,6 +3875,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
else if (getLangOpts().CPlusPlus11)
Diag(CommaLoc, diag::warn_cxx98_compat_enumerator_list_comma)
<< FixItHint::CreateRemoval(CommaLoc);
+ break;
}
}
@@ -3910,7 +3899,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
// was probably forgotten.
bool CanBeBitfield = getCurScope()->getFlags() & Scope::ClassScope;
if (!isValidAfterTypeSpecifier(CanBeBitfield)) {
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl, "enum");
+ ExpectAndConsume(tok::semi, diag::err_expected_after, "enum");
// Push this token back into the preprocessor and change our current token
// to ';' so that the rest of the code recovers as though there were an
// ';' after the definition.
@@ -3924,12 +3913,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
bool Parser::isTypeQualifier() const {
switch (Tok.getKind()) {
default: return false;
-
- // type-qualifier only in OpenCL
- case tok::kw_private:
- return getLangOpts().OpenCL;
-
- // type-qualifier
+ // type-qualifier
case tok::kw_const:
case tok::kw_volatile:
case tok::kw_restrict:
@@ -3975,16 +3959,6 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const {
case tok::kw__Decimal128:
case tok::kw___vector:
- // OpenCL specific types:
- case tok::kw_image1d_t:
- case tok::kw_image1d_array_t:
- case tok::kw_image1d_buffer_t:
- case tok::kw_image2d_t:
- case tok::kw_image2d_array_t:
- case tok::kw_image3d_t:
- case tok::kw_sampler_t:
- case tok::kw_event_t:
-
// struct-or-union-specifier (C99) or class-specifier (C++)
case tok::kw_class:
case tok::kw_struct:
@@ -4057,16 +4031,6 @@ bool Parser::isTypeSpecifierQualifier() {
case tok::kw__Decimal128:
case tok::kw___vector:
- // OpenCL specific types:
- case tok::kw_image1d_t:
- case tok::kw_image1d_array_t:
- case tok::kw_image1d_buffer_t:
- case tok::kw_image2d_t:
- case tok::kw_image2d_array_t:
- case tok::kw_image3d_t:
- case tok::kw_sampler_t:
- case tok::kw_event_t:
-
// struct-or-union-specifier (C99) or class-specifier (C++)
case tok::kw_class:
case tok::kw_struct:
@@ -4111,9 +4075,6 @@ bool Parser::isTypeSpecifierQualifier() {
return true;
- case tok::kw_private:
- return getLangOpts().OpenCL;
-
// C11 _Atomic
case tok::kw__Atomic:
return true;
@@ -4129,9 +4090,6 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
switch (Tok.getKind()) {
default: return false;
- case tok::kw_private:
- return getLangOpts().OpenCL;
-
case tok::identifier: // foo::bar
// Unfortunate hack to support "Class.factoryMethod" notation.
if (getLangOpts().ObjC1 && NextToken().is(tok::period))
@@ -4213,16 +4171,6 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::kw__Decimal128:
case tok::kw___vector:
- // OpenCL specific types:
- case tok::kw_image1d_t:
- case tok::kw_image1d_array_t:
- case tok::kw_image1d_buffer_t:
- case tok::kw_image2d_t:
- case tok::kw_image2d_array_t:
- case tok::kw_image3d_t:
- case tok::kw_sampler_t:
- case tok::kw_event_t:
-
// struct-or-union-specifier (C99) or class-specifier (C++)
case tok::kw_class:
case tok::kw_struct:
@@ -4300,7 +4248,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
}
}
-bool Parser::isConstructorDeclarator() {
+bool Parser::isConstructorDeclarator(bool IsUnqualified) {
TentativeParsingAction TPA(*this);
// Parse the C++ scope specifier.
@@ -4382,12 +4330,35 @@ bool Parser::isConstructorDeclarator() {
case tok::coloncolon:
// C(X :: Y);
// C(X :: *p);
- case tok::r_paren:
- // C(X )
// Assume this isn't a constructor, rather than assuming it's a
// constructor with an unnamed parameter of an ill-formed type.
break;
+ case tok::r_paren:
+ // C(X )
+ if (NextToken().is(tok::colon) || NextToken().is(tok::kw_try)) {
+ // Assume these were meant to be constructors:
+ // C(X) : (the name of a bit-field cannot be parenthesized).
+ // C(X) try (this is otherwise ill-formed).
+ IsConstructor = true;
+ }
+ if (NextToken().is(tok::semi) || NextToken().is(tok::l_brace)) {
+ // If we have a constructor name within the class definition,
+ // assume these were meant to be constructors:
+ // C(X) {
+ // C(X) ;
+ // ... because otherwise we would be declaring a non-static data
+ // member that is ill-formed because it's of the same type as its
+ // surrounding class.
+ //
+ // FIXME: We can actually do this whether or not the name is qualified,
+ // because if it is qualified in this context it must be being used as
+ // a constructor name. However, we do not implement that rule correctly
+ // currently, so we're somewhat conservative here.
+ IsConstructor = IsUnqualified;
+ }
+ break;
+
default:
IsConstructor = true;
break;
@@ -4426,7 +4397,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS,
while (1) {
bool isInvalid = false;
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID = 0;
SourceLocation Loc = Tok.getLocation();
@@ -4455,9 +4426,6 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS,
break;
// OpenCL qualifiers:
- case tok::kw_private:
- if (!getLangOpts().OpenCL)
- goto DoneWithTypeQuals;
case tok::kw___private:
case tok::kw___global:
case tok::kw___local:
@@ -4465,7 +4433,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS,
case tok::kw___read_only:
case tok::kw___write_only:
case tok::kw___read_write:
- ParseOpenCLQualifiers(DS);
+ ParseOpenCLQualifiers(DS.getAttributes());
break;
case tok::kw___uptr:
@@ -4506,7 +4474,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS,
DoneWithTypeQuals:
// If this is not a type-qualifier token, we're done reading type
// qualifiers. First verify that DeclSpec's are consistent.
- DS.Finish(Diags, PP);
+ DS.Finish(Diags, PP, Actions.getASTContext().getPrintingPolicy());
if (EndLoc.isValid())
DS.SetRangeEnd(EndLoc);
return;
@@ -4575,7 +4543,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
// Member pointers get special handling, since there's no place for the
// scope spec in the generic path below.
if (getLangOpts().CPlusPlus &&
- (Tok.is(tok::coloncolon) || Tok.is(tok::identifier) ||
+ (Tok.is(tok::coloncolon) ||
+ (Tok.is(tok::identifier) &&
+ (NextToken().is(tok::coloncolon) || NextToken().is(tok::less))) ||
Tok.is(tok::annot_cxxscope))) {
bool EnteringContext = D.getContext() == Declarator::FileContext ||
D.getContext() == Declarator::MemberContext;
@@ -4710,17 +4680,17 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
}
}
-static void diagnoseMisplacedEllipsis(Parser &P, Declarator &D,
- SourceLocation EllipsisLoc) {
- if (EllipsisLoc.isValid()) {
- FixItHint Insertion;
- if (!D.getEllipsisLoc().isValid()) {
- Insertion = FixItHint::CreateInsertion(D.getIdentifierLoc(), "...");
- D.setEllipsisLoc(EllipsisLoc);
- }
- P.Diag(EllipsisLoc, diag::err_misplaced_ellipsis_in_declaration)
- << FixItHint::CreateRemoval(EllipsisLoc) << Insertion << !D.hasName();
- }
+// When correcting from misplaced brackets before the identifier, the location
+// is saved inside the declarator so that other diagnostic messages can use
+// them. This extracts and returns that location, or returns the provided
+// location if a stored location does not exist.
+static SourceLocation getMissingDeclaratorIdLoc(Declarator &D,
+ SourceLocation Loc) {
+ if (D.getName().StartLocation.isInvalid() &&
+ D.getName().EndLocation.isValid())
+ return D.getName().EndLocation;
+
+ return Loc;
}
/// ParseDirectDeclarator
@@ -4768,6 +4738,14 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec());
if (getLangOpts().CPlusPlus && D.mayHaveIdentifier()) {
+ // Don't parse FOO:BAR as if it were a typo for FOO::BAR inside a class, in
+ // this context it is a bitfield. Also in range-based for statement colon
+ // may delimit for-range-declaration.
+ ColonProtectionRAIIObject X(*this,
+ D.getContext() == Declarator::MemberContext ||
+ (D.getContext() == Declarator::ForContext &&
+ getLangOpts().CPlusPlus11));
+
// ParseDeclaratorInternal might already have parsed the scope.
if (D.getCXXScopeSpec().isEmpty()) {
bool EnteringContext = D.getContext() == Declarator::FileContext ||
@@ -4802,7 +4780,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// The ellipsis was put in the wrong place. Recover, and explain to
// the user what they should have done.
ParseDeclarator(D);
- diagnoseMisplacedEllipsis(*this, D, EllipsisLoc);
+ if (EllipsisLoc.isValid())
+ DiagnoseMisplacedEllipsisInDeclarator(EllipsisLoc, D);
return;
} else
D.setEllipsisLoc(EllipsisLoc);
@@ -4837,7 +4816,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// Once we're past the identifier, if the scope was bad, mark the
// whole declarator bad.
D.getCXXScopeSpec().isInvalid()) {
- D.SetIdentifier(0, Tok.getLocation());
+ D.SetIdentifier(nullptr, Tok.getLocation());
D.setInvalidType(true);
} else {
// Parsed the unqualified-id; update range information and move along.
@@ -4852,6 +4831,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
"There's a C++-specific check for tok::identifier above");
assert(Tok.getIdentifierInfo() && "Not an identifier?");
D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+ D.SetRangeEnd(Tok.getLocation());
ConsumeToken();
goto PastIdentifier;
} else if (Tok.is(tok::identifier) && D.diagnoseIdentifier()) {
@@ -4861,7 +4841,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
!isCXX11VirtSpecifier(Tok)) {
Diag(Tok.getLocation(), diag::err_unexpected_unqualified_id)
<< FixItHint::CreateRemoval(Tok.getLocation());
- D.SetIdentifier(0, Tok.getLocation());
+ D.SetIdentifier(nullptr, Tok.getLocation());
ConsumeToken();
goto PastIdentifier;
}
@@ -4888,7 +4868,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
} else if (D.mayOmitIdentifier()) {
// This could be something simple like "int" (in which case the declarator
// portion is empty), if an abstract-declarator is allowed.
- D.SetIdentifier(0, Tok.getLocation());
+ D.SetIdentifier(nullptr, Tok.getLocation());
// The grammar for abstract-pack-declarator does not allow grouping parens.
// FIXME: Revisit this once core issue 1488 is resolved.
@@ -4898,10 +4878,14 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
} else {
if (Tok.getKind() == tok::annot_pragma_parser_crash)
LLVM_BUILTIN_TRAP;
- if (D.getContext() == Declarator::MemberContext)
- Diag(Tok, diag::err_expected_member_name_or_semi)
- << D.getDeclSpec().getSourceRange();
- else if (getLangOpts().CPlusPlus) {
+ if (Tok.is(tok::l_square))
+ return ParseMisplacedBracketDeclarator(D);
+ if (D.getContext() == Declarator::MemberContext) {
+ Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
+ diag::err_expected_member_name_or_semi)
+ << (D.getDeclSpec().isEmpty() ? SourceRange()
+ : D.getDeclSpec().getSourceRange());
+ } else if (getLangOpts().CPlusPlus) {
if (Tok.is(tok::period) || Tok.is(tok::arrow))
Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
else {
@@ -4910,12 +4894,16 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id)
<< getLangOpts().CPlusPlus;
else
- Diag(Tok, diag::err_expected_unqualified_id)
+ Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
+ diag::err_expected_unqualified_id)
<< getLangOpts().CPlusPlus;
}
- } else
- Diag(Tok, diag::err_expected_ident_lparen);
- D.SetIdentifier(0, Tok.getLocation());
+ } else {
+ Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
+ diag::err_expected_either)
+ << tok::identifier << tok::l_paren;
+ }
+ D.SetIdentifier(nullptr, Tok.getLocation());
D.setInvalidType(true);
}
@@ -5051,7 +5039,7 @@ void Parser::ParseParenDeclarator(Declarator &D) {
// An ellipsis cannot be placed outside parentheses.
if (EllipsisLoc.isValid())
- diagnoseMisplacedEllipsis(*this, D, EllipsisLoc);
+ DiagnoseMisplacedEllipsisInDeclarator(EllipsisLoc, D);
return;
}
@@ -5060,7 +5048,7 @@ void Parser::ParseParenDeclarator(Declarator &D) {
// argument list. Recognize that this declarator will never have an
// identifier (and remember where it would have been), then call into
// ParseFunctionDeclarator to handle of argument list.
- D.SetIdentifier(0, Tok.getLocation());
+ D.SetIdentifier(nullptr, Tok.getLocation());
// Enter function-declaration scope, limiting any declarators to the
// function prototype scope, including parameter declarators.
@@ -5122,7 +5110,6 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
ParsedAttributes FnAttrs(AttrFactory);
TypeResult TrailingReturnType;
- Actions.ActOnStartFunctionDeclarator();
/* LocalEndLoc is the end location for the local FunctionTypeLoc.
EndLoc is the end location for the function declarator.
They differ for trailing return types. */
@@ -5191,6 +5178,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
// FIXME: currently, "static" case isn't handled correctly.
bool IsCXX11MemberFunction =
getLangOpts().CPlusPlus11 &&
+ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
(D.getContext() == Declarator::MemberContext
? !D.getDeclSpec().isFriendSpecified()
: D.getContext() == Declarator::FileContext &&
@@ -5246,12 +5234,10 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
DynamicExceptionRanges.data(),
DynamicExceptions.size(),
NoexceptExpr.isUsable() ?
- NoexceptExpr.get() : 0,
+ NoexceptExpr.get() : nullptr,
StartLoc, LocalEndLoc, D,
TrailingReturnType),
FnAttrs, EndLoc);
-
- Actions.ActOnEndFunctionDeclarator();
}
/// isFunctionDeclaratorIdentifierList - This parameter list may have an
@@ -5303,10 +5289,10 @@ void Parser::ParseFunctionDeclaratorIdentifierList(
// Maintain an efficient lookup of params we have seen so far.
llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar;
- while (1) {
+ do {
// If this isn't an identifier, report the error and skip until ')'.
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
// Forget we parsed anything.
ParamInfo.clear();
@@ -5326,17 +5312,13 @@ void Parser::ParseFunctionDeclaratorIdentifierList(
// Remember this identifier in ParamInfo.
ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
Tok.getLocation(),
- 0));
+ nullptr));
}
// Eat the identifier.
ConsumeToken();
-
// The list continues if we see a comma.
- if (Tok.isNot(tok::comma))
- break;
- ConsumeToken();
- }
+ } while (TryConsumeToken(tok::comma));
}
/// ParseParameterDeclarationClause - Parse a (possibly empty) parameter-list
@@ -5375,13 +5357,11 @@ void Parser::ParseParameterDeclarationClause(
ParsedAttributes &FirstArgAttrs,
SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
SourceLocation &EllipsisLoc) {
- while (1) {
- if (Tok.is(tok::ellipsis)) {
- // FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq
- // before deciding this was a parameter-declaration-clause.
- EllipsisLoc = ConsumeToken(); // Consume the ellipsis.
+ do {
+ // FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq
+ // before deciding this was a parameter-declaration-clause.
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
break;
- }
// Parse the declaration-specifiers.
// Just use the ParsingDeclaration "scope" of the declarator.
@@ -5422,11 +5402,11 @@ void Parser::ParseParameterDeclarationClause(
// DefArgToks is used when the parsing of default arguments needs
// to be delayed.
- CachedTokens *DefArgToks = 0;
+ CachedTokens *DefArgToks = nullptr;
// If no parameter was specified, verify that *something* was specified,
// otherwise we have a missing type and identifier.
- if (DS.isEmpty() && ParmDeclarator.getIdentifier() == 0 &&
+ if (DS.isEmpty() && ParmDeclarator.getIdentifier() == nullptr &&
ParmDeclarator.getNumTypeObjects() == 0) {
// Completely missing, emit error.
Diag(DSStart, diag::err_missing_param);
@@ -5455,8 +5435,8 @@ void Parser::ParseParameterDeclarationClause(
if (!ConsumeAndStoreInitializer(*DefArgToks, CIK_DefaultArgument)) {
delete DefArgToks;
- DefArgToks = 0;
- Actions.ActOnParamDefaultArgumentError(Param);
+ DefArgToks = nullptr;
+ Actions.ActOnParamDefaultArgumentError(Param, EqualLoc);
} else {
// Mark the end of the default argument so that we know when to
// stop when we parse it later on.
@@ -5485,12 +5465,12 @@ void Parser::ParseParameterDeclarationClause(
} else
DefArgResult = ParseAssignmentExpression();
if (DefArgResult.isInvalid()) {
- Actions.ActOnParamDefaultArgumentError(Param);
+ Actions.ActOnParamDefaultArgumentError(Param, EqualLoc);
SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch);
} else {
// Inform the actions module about the default argument
Actions.ActOnParamDefaultArgument(Param, EqualLoc,
- DefArgResult.take());
+ DefArgResult.get());
}
}
}
@@ -5500,26 +5480,17 @@ void Parser::ParseParameterDeclarationClause(
Param, DefArgToks));
}
- // If the next token is a comma, consume it and keep reading arguments.
- if (Tok.isNot(tok::comma)) {
- if (Tok.is(tok::ellipsis)) {
- EllipsisLoc = ConsumeToken(); // Consume the ellipsis.
-
- if (!getLangOpts().CPlusPlus) {
- // We have ellipsis without a preceding ',', which is ill-formed
- // in C. Complain and provide the fix.
- Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis)
- << FixItHint::CreateInsertion(EllipsisLoc, ", ");
- }
- }
-
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc) &&
+ !getLangOpts().CPlusPlus) {
+ // We have ellipsis without a preceding ',', which is ill-formed
+ // in C. Complain and provide the fix.
+ Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis)
+ << FixItHint::CreateInsertion(EllipsisLoc, ", ");
break;
}
- // Consume the comma.
- ConsumeToken();
- }
-
+ // If the next token is a comma, consume it and keep reading arguments.
+ } while (TryConsumeToken(tok::comma));
}
/// [C90] direct-declarator '[' constant-expression[opt] ']'
@@ -5544,8 +5515,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
MaybeParseCXX11Attributes(attrs);
// Remember that we parsed the empty array type.
- ExprResult NumElements;
- D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0,
+ D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, nullptr,
T.getOpenLocation(),
T.getCloseLocation()),
attrs, T.getCloseLocation());
@@ -5562,7 +5532,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
// Remember that we parsed a array type, and remember its features.
D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false,
- ExprRes.release(),
+ ExprRes.get(),
T.getOpenLocation(),
T.getCloseLocation()),
attrs, T.getCloseLocation());
@@ -5571,8 +5541,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
// If valid, this location is the position where we read the 'static' keyword.
SourceLocation StaticLoc;
- if (Tok.is(tok::kw_static))
- StaticLoc = ConsumeToken();
+ TryConsumeToken(tok::kw_static, StaticLoc);
// If there is a type-qualifier-list, read it now.
// Type qualifiers in an array subscript are a C99 feature.
@@ -5581,8 +5550,8 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
// If we haven't already read 'static', check to see if there is one after the
// type-qualifier-list.
- if (!StaticLoc.isValid() && Tok.is(tok::kw_static))
- StaticLoc = ConsumeToken();
+ if (!StaticLoc.isValid())
+ TryConsumeToken(tok::kw_static, StaticLoc);
// Handle "direct-declarator [ type-qual-list[opt] * ]".
bool isStar = false;
@@ -5633,12 +5602,102 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
// Remember that we parsed a array type, and remember its features.
D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(),
StaticLoc.isValid(), isStar,
- NumElements.release(),
+ NumElements.get(),
T.getOpenLocation(),
T.getCloseLocation()),
attrs, T.getCloseLocation());
}
+/// Diagnose brackets before an identifier.
+void Parser::ParseMisplacedBracketDeclarator(Declarator &D) {
+ assert(Tok.is(tok::l_square) && "Missing opening bracket");
+ assert(!D.mayOmitIdentifier() && "Declarator cannot omit identifier");
+
+ SourceLocation StartBracketLoc = Tok.getLocation();
+ Declarator TempDeclarator(D.getDeclSpec(), D.getContext());
+
+ while (Tok.is(tok::l_square)) {
+ ParseBracketDeclarator(TempDeclarator);
+ }
+
+ // Stuff the location of the start of the brackets into the Declarator.
+ // The diagnostics from ParseDirectDeclarator will make more sense if
+ // they use this location instead.
+ if (Tok.is(tok::semi))
+ D.getName().EndLocation = StartBracketLoc;
+
+ SourceLocation SuggestParenLoc = Tok.getLocation();
+
+ // Now that the brackets are removed, try parsing the declarator again.
+ ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
+
+ // Something went wrong parsing the brackets, in which case,
+ // ParseBracketDeclarator has emitted an error, and we don't need to emit
+ // one here.
+ if (TempDeclarator.getNumTypeObjects() == 0)
+ return;
+
+ // Determine if parens will need to be suggested in the diagnostic.
+ bool NeedParens = false;
+ if (D.getNumTypeObjects() != 0) {
+ switch (D.getTypeObject(D.getNumTypeObjects() - 1).Kind) {
+ case DeclaratorChunk::Pointer:
+ case DeclaratorChunk::Reference:
+ case DeclaratorChunk::BlockPointer:
+ case DeclaratorChunk::MemberPointer:
+ NeedParens = true;
+ break;
+ case DeclaratorChunk::Array:
+ case DeclaratorChunk::Function:
+ case DeclaratorChunk::Paren:
+ break;
+ }
+ }
+
+ if (NeedParens) {
+ // Create a DeclaratorChunk for the inserted parens.
+ ParsedAttributes attrs(AttrFactory);
+ SourceLocation EndLoc = PP.getLocForEndOfToken(D.getLocEnd());
+ D.AddTypeInfo(DeclaratorChunk::getParen(SuggestParenLoc, EndLoc), attrs,
+ SourceLocation());
+ }
+
+ // Adding back the bracket info to the end of the Declarator.
+ for (unsigned i = 0, e = TempDeclarator.getNumTypeObjects(); i < e; ++i) {
+ const DeclaratorChunk &Chunk = TempDeclarator.getTypeObject(i);
+ ParsedAttributes attrs(AttrFactory);
+ attrs.set(Chunk.Common.AttrList);
+ D.AddTypeInfo(Chunk, attrs, SourceLocation());
+ }
+
+ // The missing identifier would have been diagnosed in ParseDirectDeclarator.
+ // If parentheses are required, always suggest them.
+ if (!D.getIdentifier() && !NeedParens)
+ return;
+
+ SourceLocation EndBracketLoc = TempDeclarator.getLocEnd();
+
+ // Generate the move bracket error message.
+ SourceRange BracketRange(StartBracketLoc, EndBracketLoc);
+ SourceLocation EndLoc = PP.getLocForEndOfToken(D.getLocEnd());
+
+ if (NeedParens) {
+ Diag(EndLoc, diag::err_brackets_go_after_unqualified_id)
+ << getLangOpts().CPlusPlus
+ << FixItHint::CreateInsertion(SuggestParenLoc, "(")
+ << FixItHint::CreateInsertion(EndLoc, ")")
+ << FixItHint::CreateInsertionFromRange(
+ EndLoc, CharSourceRange(BracketRange, true))
+ << FixItHint::CreateRemoval(BracketRange);
+ } else {
+ Diag(EndLoc, diag::err_brackets_go_after_unqualified_id)
+ << getLangOpts().CPlusPlus
+ << FixItHint::CreateInsertionFromRange(
+ EndLoc, CharSourceRange(BracketRange, true))
+ << FixItHint::CreateRemoval(BracketRange);
+ }
+}
+
/// [GNU] typeof-specifier:
/// typeof ( expressions )
/// typeof ( type-name )
@@ -5674,11 +5733,12 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
return;
}
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
// Check for duplicate type specifiers (e.g. "int typeof(int)").
if (DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, PrevSpec,
- DiagID, CastTy))
+ DiagID, CastTy,
+ Actions.getASTContext().getPrintingPolicy()))
Diag(StartLoc, DiagID) << PrevSpec;
return;
}
@@ -5696,11 +5756,12 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
return;
}
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
// Check for duplicate type specifiers (e.g. "int typeof(int)").
if (DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc, PrevSpec,
- DiagID, Operand.get()))
+ DiagID, Operand.get(),
+ Actions.getASTContext().getPrintingPolicy()))
Diag(StartLoc, DiagID) << PrevSpec;
}
@@ -5731,10 +5792,11 @@ void Parser::ParseAtomicSpecifier(DeclSpec &DS) {
DS.setTypeofParensRange(T.getRange());
DS.SetRangeEnd(T.getCloseLocation());
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
if (DS.SetTypeSpecType(DeclSpec::TST_atomic, StartLoc, PrevSpec,
- DiagID, Result.release()))
+ DiagID, Result.get(),
+ Actions.getASTContext().getPrintingPolicy()))
Diag(StartLoc, DiagID) << PrevSpec;
}
@@ -5774,6 +5836,7 @@ bool Parser::TryAltiVecVectorTokenOutOfLine() {
bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc,
const char *&PrevSpec, unsigned &DiagID,
bool &isInvalid) {
+ const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
if (Tok.getIdentifierInfo() == Ident_vector) {
Token Next = NextToken();
switch (Next.getKind()) {
@@ -5788,15 +5851,15 @@ bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc,
case tok::kw_double:
case tok::kw_bool:
case tok::kw___pixel:
- isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
+ isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy);
return true;
case tok::identifier:
if (Next.getIdentifierInfo() == Ident_pixel) {
- isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
+ isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID,Policy);
return true;
}
if (Next.getIdentifierInfo() == Ident_bool) {
- isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
+ isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID,Policy);
return true;
}
break;
@@ -5805,11 +5868,11 @@ bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc,
}
} else if ((Tok.getIdentifierInfo() == Ident_pixel) &&
DS.isTypeAltiVecVector()) {
- isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID);
+ isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID, Policy);
return true;
} else if ((Tok.getIdentifierInfo() == Ident_bool) &&
DS.isTypeAltiVecVector()) {
- isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID);
+ isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID, Policy);
return true;
}
return false;
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index dd29f99ffc71..6200363b3bc5 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -13,9 +13,12 @@
#include "clang/Parse/Parser.h"
#include "RAIIObjectsForParser.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/Basic/Attributes.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/OperatorKinds.h"
-#include "clang/AST/DeclTemplate.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
@@ -61,11 +64,11 @@ Decl *Parser::ParseNamespace(unsigned Context,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteNamespaceDecl(getCurScope());
cutOffParsing();
- return 0;
+ return nullptr;
}
SourceLocation IdentLoc;
- IdentifierInfo *Ident = 0;
+ IdentifierInfo *Ident = nullptr;
std::vector<SourceLocation> ExtraIdentLoc;
std::vector<IdentifierInfo*> ExtraIdent;
std::vector<SourceLocation> ExtraNamespaceLoc;
@@ -90,11 +93,11 @@ Decl *Parser::ParseNamespace(unsigned Context,
}
if (Tok.is(tok::equal)) {
- if (Ident == 0) {
- Diag(Tok, diag::err_expected_ident);
+ if (!Ident) {
+ Diag(Tok, diag::err_expected) << tok::identifier;
// Skip to end of the definition and eat the ';'.
SkipUntil(tok::semi);
- return 0;
+ return nullptr;
}
if (!attrs.empty())
Diag(attrTok, diag::err_unexpected_namespace_attributes_alias);
@@ -111,9 +114,13 @@ Decl *Parser::ParseNamespace(unsigned Context,
Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon)
<< SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back());
}
- Diag(Tok, Ident ? diag::err_expected_lbrace :
- diag::err_expected_ident_lbrace);
- return 0;
+
+ if (Ident)
+ Diag(Tok, diag::err_expected) << tok::l_brace;
+ else
+ Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace;
+
+ return nullptr;
}
if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() ||
@@ -125,7 +132,7 @@ Decl *Parser::ParseNamespace(unsigned Context,
}
Diag(T.getOpenLocation(), diag::err_namespace_nonnamespace_scope);
SkipUntil(tok::r_brace);
- return 0;
+ return nullptr;
}
if (!ExtraIdent.empty()) {
@@ -195,7 +202,7 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc,
ParsedAttributes& attrs,
BalancedDelimiterTracker &Tracker) {
if (index == Ident.size()) {
- while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
MaybeParseMicrosoftAttributes(attrs);
@@ -239,7 +246,7 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteNamespaceAliasDecl(getCurScope());
cutOffParsing();
- return 0;
+ return nullptr;
}
CXXScopeSpec SS;
@@ -250,7 +257,7 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
Diag(Tok, diag::err_expected_namespace_name);
// Skip to end of the definition and eat the ';'.
SkipUntil(tok::semi);
- return 0;
+ return nullptr;
}
// Parse identifier.
@@ -259,8 +266,8 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
// Eat the ';'.
DeclEnd = Tok.getLocation();
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name,
- "", tok::semi);
+ if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name))
+ SkipUntil(tok::semi);
return Actions.ActOnNamespaceAliasDef(getCurScope(), NamespaceLoc, AliasLoc, Alias,
SS, IdentLoc, Ident);
@@ -274,27 +281,16 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
/// 'extern' string-literal declaration
///
Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) {
- assert(Tok.is(tok::string_literal) && "Not a string literal!");
- SmallString<8> LangBuffer;
- bool Invalid = false;
- StringRef Lang = PP.getSpelling(Tok, LangBuffer, &Invalid);
- if (Invalid)
- return 0;
-
- // FIXME: This is incorrect: linkage-specifiers are parsed in translation
- // phase 7, so string-literal concatenation is supposed to occur.
- // extern "" "C" "" "+" "+" { } is legal.
- if (Tok.hasUDSuffix())
- Diag(Tok, diag::err_invalid_string_udl);
- SourceLocation Loc = ConsumeStringToken();
+ assert(isTokenStringLiteral() && "Not a string literal!");
+ ExprResult Lang = ParseStringLiteralExpression(false);
ParseScope LinkageScope(this, Scope::DeclScope);
- Decl *LinkageSpec
- = Actions.ActOnStartLinkageSpecification(getCurScope(),
- DS.getSourceRange().getBegin(),
- Loc, Lang,
- Tok.is(tok::l_brace) ? Tok.getLocation()
- : SourceLocation());
+ Decl *LinkageSpec =
+ Lang.isInvalid()
+ ? nullptr
+ : Actions.ActOnStartLinkageSpecification(
+ getCurScope(), DS.getSourceRange().getBegin(), Lang.get(),
+ Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation());
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
@@ -308,8 +304,9 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) {
// ... but anyway remember that such an "extern" was seen.
DS.setExternInLinkageSpec(true);
ParseExternalDeclaration(attrs, &DS);
- return Actions.ActOnFinishLinkageSpecification(getCurScope(), LinkageSpec,
- SourceLocation());
+ return LinkageSpec ? Actions.ActOnFinishLinkageSpecification(
+ getCurScope(), LinkageSpec, SourceLocation())
+ : nullptr;
}
DS.abort();
@@ -318,16 +315,48 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) {
BalancedDelimiterTracker T(*this, tok::l_brace);
T.consumeOpen();
- while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
- ParsedAttributesWithRange attrs(AttrFactory);
- MaybeParseCXX11Attributes(attrs);
- MaybeParseMicrosoftAttributes(attrs);
- ParseExternalDeclaration(attrs);
+
+ unsigned NestedModules = 0;
+ while (true) {
+ switch (Tok.getKind()) {
+ case tok::annot_module_begin:
+ ++NestedModules;
+ ParseTopLevelDecl();
+ continue;
+
+ case tok::annot_module_end:
+ if (!NestedModules)
+ break;
+ --NestedModules;
+ ParseTopLevelDecl();
+ continue;
+
+ case tok::annot_module_include:
+ ParseTopLevelDecl();
+ continue;
+
+ case tok::eof:
+ break;
+
+ case tok::r_brace:
+ if (!NestedModules)
+ break;
+ // Fall through.
+ default:
+ ParsedAttributesWithRange attrs(AttrFactory);
+ MaybeParseCXX11Attributes(attrs);
+ MaybeParseMicrosoftAttributes(attrs);
+ ParseExternalDeclaration(attrs);
+ continue;
+ }
+
+ break;
}
T.consumeClose();
- return Actions.ActOnFinishLinkageSpecification(getCurScope(), LinkageSpec,
- T.getCloseLocation());
+ return LinkageSpec ? Actions.ActOnFinishLinkageSpecification(
+ getCurScope(), LinkageSpec, T.getCloseLocation())
+ : nullptr;
}
/// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or
@@ -346,7 +375,7 @@ Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteUsing(getCurScope());
cutOffParsing();
- return 0;
+ return nullptr;
}
// 'using namespace' means this is a using-directive.
@@ -392,14 +421,14 @@ Decl *Parser::ParseUsingDirective(unsigned Context,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteUsingDirective(getCurScope());
cutOffParsing();
- return 0;
+ return nullptr;
}
CXXScopeSpec SS;
// Parse (optional) nested-name-specifier.
ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
- IdentifierInfo *NamespcName = 0;
+ IdentifierInfo *NamespcName = nullptr;
SourceLocation IdentLoc = SourceLocation();
// Parse namespace-name.
@@ -408,7 +437,7 @@ Decl *Parser::ParseUsingDirective(unsigned Context,
// If there was invalid namespace name, skip to end of decl, and eat ';'.
SkipUntil(tok::semi);
// FIXME: Are there cases, when we would like to call ActOnUsingDirective?
- return 0;
+ return nullptr;
}
// Parse identifier.
@@ -424,10 +453,10 @@ Decl *Parser::ParseUsingDirective(unsigned Context,
// Eat ';'.
DeclEnd = Tok.getLocation();
- ExpectAndConsume(tok::semi,
- GNUAttr ? diag::err_expected_semi_after_attribute_list
- : diag::err_expected_semi_after_namespace_name,
- "", tok::semi);
+ if (ExpectAndConsume(tok::semi,
+ GNUAttr ? diag::err_expected_semi_after_attribute_list
+ : diag::err_expected_semi_after_namespace_name))
+ SkipUntil(tok::semi);
return Actions.ActOnUsingDirective(getCurScope(), UsingLoc, NamespcLoc, SS,
IdentLoc, NamespcName, attrs.getList());
@@ -461,21 +490,20 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
// Ignore optional 'typename'.
// FIXME: This is wrong; we should parse this as a typename-specifier.
- if (Tok.is(tok::kw_typename)) {
- TypenameLoc = ConsumeToken();
+ if (TryConsumeToken(tok::kw_typename, TypenameLoc))
HasTypenameKeyword = true;
- }
// Parse nested-name-specifier.
- IdentifierInfo *LastII = 0;
+ IdentifierInfo *LastII = nullptr;
ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false,
- /*MayBePseudoDtor=*/0, /*IsTypename=*/false,
+ /*MayBePseudoDtor=*/nullptr,
+ /*IsTypename=*/false,
/*LastII=*/&LastII);
// Check nested-name specifier.
if (SS.isInvalid()) {
SkipUntil(tok::semi);
- return 0;
+ return nullptr;
}
SourceLocation TemplateKWLoc;
@@ -504,7 +532,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
/*AllowConstructorName=*/ true, ParsedType(),
TemplateKWLoc, Name)) {
SkipUntil(tok::semi);
- return 0;
+ return nullptr;
}
ParsedAttributesWithRange Attrs(AttrFactory);
@@ -551,7 +579,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
Diag(Range.getBegin(), diag::err_alias_declaration_specialization)
<< SpecKind << Range;
SkipUntil(tok::semi);
- return 0;
+ return nullptr;
}
// Name must be an identifier.
@@ -559,7 +587,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
Diag(Name.StartLocation, diag::err_alias_declaration_not_identifier);
// No removal fixit: can't recover from this.
SkipUntil(tok::semi);
- return 0;
+ return nullptr;
} else if (HasTypenameKeyword)
Diag(TypenameLoc, diag::err_alias_declaration_not_identifier)
<< FixItHint::CreateRemoval(SourceRange(TypenameLoc,
@@ -568,7 +596,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
Diag(SS.getBeginLoc(), diag::err_alias_declaration_not_identifier)
<< FixItHint::CreateRemoval(SS.getRange());
- TypeAlias = ParseTypeName(0, TemplateInfo.Kind ?
+ TypeAlias = ParseTypeName(nullptr, TemplateInfo.Kind ?
Declarator::AliasTemplateContext :
Declarator::AliasDeclContext, AS, OwnedType,
&Attrs);
@@ -584,10 +612,11 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
// Eat ';'.
DeclEnd = Tok.getLocation();
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
- !Attrs.empty() ? "attributes list" :
- IsAliasDecl ? "alias declaration" : "using declaration",
- tok::semi);
+ if (ExpectAndConsume(tok::semi, diag::err_expected_after,
+ !Attrs.empty() ? "attributes list"
+ : IsAliasDecl ? "alias declaration"
+ : "using declaration"))
+ SkipUntil(tok::semi);
// Diagnose an attempt to declare a templated using-declaration.
// In C++11, alias-declarations can be templates:
@@ -600,7 +629,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
// Unfortunately, we have to bail out instead of recovering by
// ignoring the parameters, just in case the nested name specifier
// depends on the parameters.
- return 0;
+ return nullptr;
}
// "typename" keyword is allowed for identifiers only,
@@ -615,7 +644,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
if (IsAliasDecl) {
TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
MultiTemplateParamsArg TemplateParamsArg(
- TemplateParams ? TemplateParams->data() : 0,
+ TemplateParams ? TemplateParams->data() : nullptr,
TemplateParams ? TemplateParams->size() : 0);
return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg,
UsingLoc, Name, Attrs.getList(),
@@ -649,31 +678,43 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
BalancedDelimiterTracker T(*this, tok::l_paren);
if (T.consumeOpen()) {
- Diag(Tok, diag::err_expected_lparen);
+ Diag(Tok, diag::err_expected) << tok::l_paren;
SkipMalformedDecl();
- return 0;
+ return nullptr;
}
ExprResult AssertExpr(ParseConstantExpression());
if (AssertExpr.isInvalid()) {
SkipMalformedDecl();
- return 0;
+ return nullptr;
}
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", tok::semi))
- return 0;
+ ExprResult AssertMessage;
+ if (Tok.is(tok::r_paren)) {
+ Diag(Tok, getLangOpts().CPlusPlus1z
+ ? diag::warn_cxx1y_compat_static_assert_no_message
+ : diag::ext_static_assert_no_message)
+ << (getLangOpts().CPlusPlus1z
+ ? FixItHint()
+ : FixItHint::CreateInsertion(Tok.getLocation(), ", \"\""));
+ } else {
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::semi);
+ return nullptr;
+ }
- if (!isTokenStringLiteral()) {
- Diag(Tok, diag::err_expected_string_literal)
- << /*Source='static_assert'*/1;
- SkipMalformedDecl();
- return 0;
- }
+ if (!isTokenStringLiteral()) {
+ Diag(Tok, diag::err_expected_string_literal)
+ << /*Source='static_assert'*/1;
+ SkipMalformedDecl();
+ return nullptr;
+ }
- ExprResult AssertMessage(ParseStringLiteralExpression());
- if (AssertMessage.isInvalid()) {
- SkipMalformedDecl();
- return 0;
+ AssertMessage = ParseStringLiteralExpression();
+ if (AssertMessage.isInvalid()) {
+ SkipMalformedDecl();
+ return nullptr;
+ }
}
T.consumeClose();
@@ -682,8 +723,8 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
ExpectAndConsumeSemi(diag::err_expected_semi_after_static_assert);
return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc,
- AssertExpr.take(),
- AssertMessage.take(),
+ AssertExpr.get(),
+ AssertMessage.get(),
T.getCloseLocation());
}
@@ -738,7 +779,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
// C++11 [dcl.type.simple]p4:
// The operand of the decltype specifier is an unevaluated operand.
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
- 0, /*IsDecltype=*/true);
+ nullptr,/*IsDecltype=*/true);
Result = ParseExpression();
if (Result.isInvalid()) {
DS.SetTypeSpecError();
@@ -758,7 +799,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
return EndLoc;
}
- Result = Actions.ActOnDecltypeExpression(Result.take());
+ Result = Actions.ActOnDecltypeExpression(Result.get());
}
// Match the ')'
@@ -779,14 +820,15 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
}
assert(!Result.isInvalid());
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
+ const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
// Check for duplicate type specifiers (e.g. "int decltype(a)").
if (Result.get()
? DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, PrevSpec,
- DiagID, Result.release())
+ DiagID, Result.get(), Policy)
: DS.SetTypeSpecType(DeclSpec::TST_decltype_auto, StartLoc, PrevSpec,
- DiagID)) {
+ DiagID, Policy)) {
Diag(StartLoc, DiagID) << PrevSpec;
DS.SetTypeSpecError();
}
@@ -834,10 +876,11 @@ void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) {
if (T.getCloseLocation().isInvalid())
return;
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
if (DS.SetTypeSpecType(DeclSpec::TST_underlyingType, StartLoc, PrevSpec,
- DiagID, Result.release()))
+ DiagID, Result.get(),
+ Actions.getASTContext().getPrintingPolicy()))
Diag(StartLoc, DiagID) << PrevSpec;
DS.setTypeofParensRange(T.getRange());
}
@@ -963,7 +1006,7 @@ Parser::TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
}
// We have an identifier; check whether it is actually a type.
- IdentifierInfo *CorrectedII = 0;
+ IdentifierInfo *CorrectedII = nullptr;
ParsedType Type = Actions.getTypeName(*Id, IdLoc, getCurScope(), &SS, true,
false, ParsedType(),
/*IsCtorOrDtorName=*/false,
@@ -983,9 +1026,10 @@ Parser::TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
DS.SetRangeEnd(EndLocation);
DS.getTypeSpecScope() = SS;
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
- DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type);
+ DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type,
+ Actions.getASTContext().getPrintingPolicy());
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
@@ -997,8 +1041,8 @@ void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) {
Tok.is(tok::kw___virtual_inheritance)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
- attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
- AttributeList::AS_GNU);
+ attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
+ AttributeList::AS_Keyword);
}
}
@@ -1021,6 +1065,7 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) {
case tok::l_paren: // struct foo {...} ( x);
case tok::comma: // __builtin_offsetof(struct foo{...} ,
case tok::kw_operator: // struct foo operator ++() {...}
+ case tok::kw___declspec: // struct foo {...} __declspec(...)
return true;
case tok::colon:
return CouldBeBitfield; // enum E { ... } : 2;
@@ -1179,51 +1224,38 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// C++11 attributes
SourceLocation AttrFixitLoc = Tok.getLocation();
- if (TagType == DeclSpec::TST_struct &&
- !Tok.is(tok::identifier) &&
- Tok.getIdentifierInfo() &&
- (Tok.is(tok::kw___is_arithmetic) ||
- Tok.is(tok::kw___is_convertible) ||
- Tok.is(tok::kw___is_empty) ||
- Tok.is(tok::kw___is_floating_point) ||
- Tok.is(tok::kw___is_function) ||
- Tok.is(tok::kw___is_fundamental) ||
- Tok.is(tok::kw___is_integral) ||
- Tok.is(tok::kw___is_member_function_pointer) ||
- Tok.is(tok::kw___is_member_pointer) ||
- Tok.is(tok::kw___is_pod) ||
- Tok.is(tok::kw___is_pointer) ||
- Tok.is(tok::kw___is_same) ||
- Tok.is(tok::kw___is_scalar) ||
- Tok.is(tok::kw___is_signed) ||
- Tok.is(tok::kw___is_unsigned) ||
- Tok.is(tok::kw___is_void)))
- // 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
- // X", make X into a normal identifier rather than a keyword, to
- // allow libstdc++ 4.2 and libc++ to work properly.
- TryKeywordIdentFallback(true);
+ // GNU libstdc++ and libc++ use certain intrinsic names as the
+ // name of struct templates, but some are keywords in GCC >= 4.3
+ // MSVC and Clang. For compatibility, convert the token to an identifier
+ // and issue a warning diagnostic.
+ if (TagType == DeclSpec::TST_struct && !Tok.is(tok::identifier) &&
+ !Tok.isAnnotation()) {
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ // We rarely end up here so the following check is efficient.
+ if (II && II->getName().startswith("__is_"))
+ TryKeywordIdentFallback(true);
+ }
// Parse the (optional) nested-name-specifier.
CXXScopeSpec &SS = DS.getTypeSpecScope();
if (getLangOpts().CPlusPlus) {
- // "FOO : BAR" is not a potential typo for "FOO::BAR".
+ // "FOO : BAR" is not a potential typo for "FOO::BAR". In this context it
+ // is a base-specifier-list.
ColonProtectionRAIIObject X(*this);
if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext))
DS.SetTypeSpecError();
if (SS.isSet())
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
}
TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
// Parse the (optional) class name or simple-template-id.
- IdentifierInfo *Name = 0;
+ IdentifierInfo *Name = nullptr;
SourceLocation NameLoc;
- TemplateIdAnnotation *TemplateId = 0;
+ TemplateIdAnnotation *TemplateId = nullptr;
if (Tok.is(tok::identifier)) {
Name = Tok.getIdentifierInfo();
NameLoc = ConsumeToken();
@@ -1243,13 +1275,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
}
Diag(NameLoc, diag::err_explicit_spec_non_template)
- << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
- << (TagType == DeclSpec::TST_class? 0
- : TagType == DeclSpec::TST_struct? 1
- : TagType == DeclSpec::TST_union? 2
- : 3)
- << Name
- << SourceRange(LAngleLoc, RAngleLoc);
+ << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
+ << TagTokKind << Name << SourceRange(LAngleLoc, RAngleLoc);
// Strip off the last template parameter list if it was empty, since
// we've removed its template argument list.
@@ -1257,14 +1284,14 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
if (TemplateParams && TemplateParams->size() > 1) {
TemplateParams->pop_back();
} else {
- TemplateParams = 0;
+ TemplateParams = nullptr;
const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
= ParsedTemplateInfo::NonTemplate;
}
} else if (TemplateInfo.Kind
== ParsedTemplateInfo::ExplicitInstantiation) {
// Pretend this is just a forward declaration.
- TemplateParams = 0;
+ TemplateParams = nullptr;
const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
= ParsedTemplateInfo::NonTemplate;
const_cast<ParsedTemplateInfo&>(TemplateInfo).TemplateLoc
@@ -1286,6 +1313,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
if (SS.isNotEmpty())
Range.setBegin(SS.getBeginLoc());
+ // FIXME: Name may be null here.
Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template)
<< TemplateId->Name << static_cast<int>(TemplateId->Kind) << Range;
@@ -1318,11 +1346,12 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// new struct s;
// or
// &T::operator struct s;
- // For these, DSC is DSC_type_specifier.
+ // For these, DSC is DSC_type_specifier or DSC_alias_declaration.
// If there are attributes after class name, parse them.
MaybeParseCXX11Attributes(Attributes);
+ const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
Sema::TagUseKind TUK;
if (DSC == DSC_trailing)
TUK = Sema::TUK_Reference;
@@ -1375,14 +1404,15 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TUK = Sema::TUK_Reference;
PA.Revert();
- } else if (DSC != DSC_type_specifier &&
+ } else if (!isTypeSpecifier(DSC) &&
(Tok.is(tok::semi) ||
(Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(false)))) {
TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration;
if (Tok.isNot(tok::semi)) {
+ const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();
// A semicolon was missing after this declaration. Diagnose and recover.
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
- DeclSpec::getSpecifierName(TagType));
+ ExpectAndConsume(tok::semi, diag::err_expected_after,
+ DeclSpec::getSpecifierName(TagType, PPol));
PP.EnterToken(Tok);
Tok.setKind(tok::semi);
}
@@ -1424,7 +1454,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
if (DS.getTypeSpecType() != DeclSpec::TST_error) {
// We have a declaration or reference to an anonymous class.
Diag(StartLoc, diag::err_anon_type_definition)
- << DeclSpec::getSpecifierName(TagType);
+ << DeclSpec::getSpecifierName(TagType, Policy);
}
// If we are parsing a definition and stop at a base-clause, continue on
@@ -1503,7 +1533,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
if (TUK == Sema::TUK_Friend) {
Diag(DS.getFriendSpecLoc(), diag::err_friend_explicit_instantiation);
- TemplateParams = 0;
+ TemplateParams = nullptr;
} else {
SourceLocation LAngleLoc =
PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
@@ -1516,25 +1546,19 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// "template<>", so that we treat this construct as a class
// template specialization.
FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
- 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, 0, 0,
- LAngleLoc));
+ 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, nullptr,
+ 0, LAngleLoc));
TemplateParams = &FakedParamLists;
}
}
// Build the class template specialization.
- TagOrTempResult
- = Actions.ActOnClassTemplateSpecialization(getCurScope(), TagType, TUK,
- StartLoc, DS.getModulePrivateSpecLoc(), SS,
- TemplateId->Template,
- TemplateId->TemplateNameLoc,
- TemplateId->LAngleLoc,
- TemplateArgsPtr,
- TemplateId->RAngleLoc,
- attrs.getList(),
- MultiTemplateParamsArg(
- TemplateParams? &(*TemplateParams)[0] : 0,
- TemplateParams? TemplateParams->size() : 0));
+ TagOrTempResult = Actions.ActOnClassTemplateSpecialization(
+ getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(),
+ *TemplateId, attrs.getList(),
+ MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0]
+ : nullptr,
+ TemplateParams ? TemplateParams->size() : 0));
}
} else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
TUK == Sema::TUK_Declaration) {
@@ -1560,7 +1584,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TagType, StartLoc, SS,
Name, NameLoc, attrs.getList(),
MultiTemplateParamsArg(
- TemplateParams? &(*TemplateParams)[0] : 0,
+ TemplateParams? &(*TemplateParams)[0]
+ : nullptr,
TemplateParams? TemplateParams->size() : 0));
} else {
if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition)
@@ -1572,7 +1597,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// recover by ignoring the 'template' keyword.
Diag(Tok, diag::err_template_defn_explicit_instantiation)
<< 1 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc);
- TemplateParams = 0;
+ TemplateParams = nullptr;
}
bool IsDependent = false;
@@ -1591,7 +1616,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
DS.getModulePrivateSpecLoc(),
TParams, Owned, IsDependent,
SourceLocation(), false,
- clang::TypeResult());
+ clang::TypeResult(),
+ DSC == DSC_type_specifier);
// If ActOnTag said the type was dependent, try again with the
// less common call.
@@ -1614,17 +1640,18 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get());
}
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
bool Result;
if (!TypeResult.isInvalid()) {
Result = DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc,
NameLoc.isValid() ? NameLoc : StartLoc,
- PrevSpec, DiagID, TypeResult.get());
+ PrevSpec, DiagID, TypeResult.get(), Policy);
} else if (!TagOrTempResult.isInvalid()) {
Result = DS.SetTypeSpecType(TagType, StartLoc,
NameLoc.isValid() ? NameLoc : StartLoc,
- PrevSpec, DiagID, TagOrTempResult.get(), Owned);
+ PrevSpec, DiagID, TagOrTempResult.get(), Owned,
+ Policy);
} else {
DS.SetTypeSpecError();
return;
@@ -1645,8 +1672,9 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
if (TUK == Sema::TUK_Definition &&
(TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) {
if (Tok.isNot(tok::semi)) {
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
- DeclSpec::getSpecifierName(TagType));
+ const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();
+ ExpectAndConsume(tok::semi, diag::err_expected_after,
+ DeclSpec::getSpecifierName(TagType, PPol));
// Push this token back into the preprocessor and change our current token
// to ';' so that the rest of the code recovers as though there were an
// ';' after the definition.
@@ -1684,10 +1712,8 @@ void Parser::ParseBaseClause(Decl *ClassDecl) {
// If the next token is a comma, consume it and keep reading
// base-specifiers.
- if (Tok.isNot(tok::comma)) break;
-
- // Consume the comma.
- ConsumeToken();
+ if (!TryConsumeToken(tok::comma))
+ break;
}
// Attach the base specifiers
@@ -1713,10 +1739,8 @@ Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {
MaybeParseCXX11Attributes(Attributes);
// Parse the 'virtual' keyword.
- if (Tok.is(tok::kw_virtual)) {
- ConsumeToken();
+ if (TryConsumeToken(tok::kw_virtual))
IsVirtual = true;
- }
CheckMisplacedCXX11Attribute(Attributes, StartLoc);
@@ -1753,9 +1777,8 @@ Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {
// actually part of the base-specifier-list grammar productions, but we
// parse it here for convenience.
SourceLocation EllipsisLoc;
- if (Tok.is(tok::ellipsis))
- EllipsisLoc = ConsumeToken();
-
+ TryConsumeToken(tok::ellipsis, EllipsisLoc);
+
// Find the complete source range for the base-specifier.
SourceRange Range(StartLoc, EndLocation);
@@ -1789,12 +1812,12 @@ void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
Decl *ThisDecl) {
// We just declared a member function. If this member function
// has any default arguments, we'll need to parse them later.
- LateParsedMethodDeclaration *LateMethod = 0;
+ LateParsedMethodDeclaration *LateMethod = nullptr;
DeclaratorChunk::FunctionTypeInfo &FTI
= DeclaratorInfo.getFunctionTypeInfo();
- for (unsigned ParamIdx = 0; ParamIdx < FTI.NumArgs; ++ParamIdx) {
- if (LateMethod || FTI.ArgInfo[ParamIdx].DefaultArgTokens) {
+ 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.
@@ -1804,17 +1827,16 @@ void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
// Add all of the parameters prior to this one (they don't
// have default arguments).
- LateMethod->DefaultArgs.reserve(FTI.NumArgs);
+ LateMethod->DefaultArgs.reserve(FTI.NumParams);
for (unsigned I = 0; I < ParamIdx; ++I)
LateMethod->DefaultArgs.push_back(
- LateParsedDefaultArgument(FTI.ArgInfo[I].Param));
+ LateParsedDefaultArgument(FTI.Params[I].Param));
}
// Add this parameter to the list of parameters (it may or may
// not have a default argument).
- LateMethod->DefaultArgs.push_back(
- LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param,
- FTI.ArgInfo[ParamIdx].DefaultArgTokens));
+ LateMethod->DefaultArgs.push_back(LateParsedDefaultArgument(
+ FTI.Params[ParamIdx].Param, FTI.Params[ParamIdx].DefaultArgTokens));
}
}
}
@@ -1826,29 +1848,27 @@ void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
/// override
/// final
VirtSpecifiers::Specifier Parser::isCXX11VirtSpecifier(const Token &Tok) const {
- if (!getLangOpts().CPlusPlus)
+ if (!getLangOpts().CPlusPlus || Tok.isNot(tok::identifier))
return VirtSpecifiers::VS_None;
- if (Tok.is(tok::identifier)) {
- IdentifierInfo *II = Tok.getIdentifierInfo();
+ IdentifierInfo *II = Tok.getIdentifierInfo();
- // Initialize the contextual keywords.
- if (!Ident_final) {
- Ident_final = &PP.getIdentifierTable().get("final");
- if (getLangOpts().MicrosoftExt)
- Ident_sealed = &PP.getIdentifierTable().get("sealed");
- Ident_override = &PP.getIdentifierTable().get("override");
- }
+ // Initialize the contextual keywords.
+ if (!Ident_final) {
+ Ident_final = &PP.getIdentifierTable().get("final");
+ if (getLangOpts().MicrosoftExt)
+ Ident_sealed = &PP.getIdentifierTable().get("sealed");
+ Ident_override = &PP.getIdentifierTable().get("override");
+ }
- if (II == Ident_override)
- return VirtSpecifiers::VS_Override;
+ if (II == Ident_override)
+ return VirtSpecifiers::VS_Override;
- if (II == Ident_sealed)
- return VirtSpecifiers::VS_Sealed;
+ if (II == Ident_sealed)
+ return VirtSpecifiers::VS_Sealed;
- if (II == Ident_final)
- return VirtSpecifiers::VS_Final;
- }
+ if (II == Ident_final)
+ return VirtSpecifiers::VS_Final;
return VirtSpecifiers::VS_None;
}
@@ -1867,7 +1887,7 @@ void Parser::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS,
// C++ [class.mem]p8:
// A virt-specifier-seq shall contain at most one of each virt-specifier.
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
if (VS.SetSpecifier(Specifier, Tok.getLocation(), PrevSpec))
Diag(Tok.getLocation(), diag::err_duplicate_virt_specifier)
<< PrevSpec
@@ -1891,24 +1911,52 @@ void Parser::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS,
}
/// isCXX11FinalKeyword - Determine whether the next token is a C++11
-/// contextual 'final' keyword.
+/// 'final' or Microsoft 'sealed' contextual keyword.
bool Parser::isCXX11FinalKeyword() const {
- if (!getLangOpts().CPlusPlus)
- return false;
+ VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier();
+ return Specifier == VirtSpecifiers::VS_Final ||
+ Specifier == VirtSpecifiers::VS_Sealed;
+}
- if (!Tok.is(tok::identifier))
- return false;
+/// \brief Parse a C++ member-declarator up to, but not including, the optional
+/// brace-or-equal-initializer or pure-specifier.
+void Parser::ParseCXXMemberDeclaratorBeforeInitializer(
+ Declarator &DeclaratorInfo, VirtSpecifiers &VS, ExprResult &BitfieldSize,
+ LateParsedAttrList &LateParsedAttrs) {
+ // member-declarator:
+ // declarator pure-specifier[opt]
+ // declarator brace-or-equal-initializer[opt]
+ // identifier[opt] ':' constant-expression
+ if (Tok.isNot(tok::colon))
+ ParseDeclarator(DeclaratorInfo);
- // Initialize the contextual keywords.
- if (!Ident_final) {
- Ident_final = &PP.getIdentifierTable().get("final");
- if (getLangOpts().MicrosoftExt)
- Ident_sealed = &PP.getIdentifierTable().get("sealed");
- Ident_override = &PP.getIdentifierTable().get("override");
+ if (!DeclaratorInfo.isFunctionDeclarator() && TryConsumeToken(tok::colon)) {
+ BitfieldSize = ParseConstantExpression();
+ if (BitfieldSize.isInvalid())
+ SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
+ } else
+ ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface);
+
+ // If a simple-asm-expr is present, parse it.
+ if (Tok.is(tok::kw_asm)) {
+ SourceLocation Loc;
+ ExprResult AsmLabel(ParseSimpleAsm(&Loc));
+ if (AsmLabel.isInvalid())
+ SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
+
+ DeclaratorInfo.setAsmLabel(AsmLabel.get());
+ DeclaratorInfo.SetRangeEnd(Loc);
}
- return Tok.getIdentifierInfo() == Ident_final ||
- Tok.getIdentifierInfo() == Ident_sealed;
+ // If attributes exist after the declarator, but before an '{', parse them.
+ MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs);
+
+ // For compatibility with code written to older Clang, also accept a
+ // virt-specifier *after* the GNU attributes.
+ // FIXME: If we saw any attributes that are known to GCC followed by a
+ // virt-specifier, issue a GCC-compat warning.
+ if (BitfieldSize.isUnset() && VS.isUnset())
+ ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface);
}
/// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration.
@@ -1962,6 +2010,14 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
return;
}
+ // Turn on colon protection early, while parsing declspec, although there is
+ // nothing to protect there. It prevents from false errors if error recovery
+ // incorrectly determines where the declspec ends, as in the example:
+ // struct A { enum class B { C }; };
+ // const int C = 4;
+ // struct D { A::B : C; };
+ ColonProtectionRAIIObject X(*this);
+
// Access declarations.
bool MalformedTypeSpec = false;
if (!TemplateInfo.Kind &&
@@ -1993,17 +2049,17 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
}
// TODO: recover from mistakenly-qualified operator declarations.
- if (ExpectAndConsume(tok::semi,
- diag::err_expected_semi_after,
- "access declaration",
- tok::semi))
+ if (ExpectAndConsume(tok::semi, diag::err_expected_after,
+ "access declaration")) {
+ SkipUntil(tok::semi);
return;
+ }
Actions.ActOnUsingDeclaration(getCurScope(), AS,
/* HasUsingKeyword */ false,
SourceLocation(),
SS, Name,
- /* AttrList */ 0,
+ /* AttrList */ nullptr,
/* HasTypenameKeyword */ false,
SourceLocation());
return;
@@ -2036,10 +2092,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
TemplateInfo, TemplateDiags);
}
- // Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it
- // is a bitfield.
- ColonProtectionRAIIObject X(*this);
-
ParsedAttributesWithRange attrs(AttrFactory);
ParsedAttributesWithRange FnAttrs(AttrFactory);
// Optional C++11 attribute-specifier
@@ -2078,9 +2130,13 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
DS.takeAttributesFrom(attrs);
if (MalformedTypeSpec)
DS.SetTypeSpecError();
+
ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class,
&CommonLateParsedAttrs);
+ // Turn off colon protection that was set for declspec.
+ X.restore();
+
// If we had a free-standing type definition with a missing semicolon, we
// may get this far before the problem becomes obvious.
if (DS.hasTagDefinition() &&
@@ -2090,12 +2146,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
return;
MultiTemplateParamsArg TemplateParams(
- TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0,
+ TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data()
+ : nullptr,
TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0);
- if (Tok.is(tok::semi)) {
- ConsumeToken();
-
+ if (TryConsumeToken(tok::semi)) {
if (DS.isFriendSpecified())
ProhibitAttributes(FnAttrs);
@@ -2114,30 +2169,30 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
SourceLocation EqualLoc;
bool HasInitializer = false;
ExprResult Init;
- if (Tok.isNot(tok::colon)) {
- // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
- ColonProtectionRAIIObject X(*this);
- // Parse the first declarator.
- ParseDeclarator(DeclaratorInfo);
- // Error parsing the declarator?
- if (!DeclaratorInfo.hasName()) {
- // If so, skip until the semi-colon or a }.
- SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
- if (Tok.is(tok::semi))
- ConsumeToken();
- return;
- }
+ SmallVector<Decl *, 8> DeclsInGroup;
+ ExprResult BitfieldSize;
+ bool ExpectSemi = true;
- ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface);
+ // Parse the first declarator.
+ ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize,
+ LateParsedAttrs);
- // If attributes exist after the declarator, but before an '{', parse them.
- MaybeParseGNUAttributes(DeclaratorInfo, &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);
+ TryConsumeToken(tok::semi);
+ return;
+ }
- // MSVC permits pure specifier on inline functions declared at class scope.
+ // Check for a member function definition.
+ if (BitfieldSize.isUnset()) {
+ // MSVC permits pure specifier on inline functions defined at class scope.
// Hence check for =0 before checking for function definition.
if (getLangOpts().MicrosoftExt && Tok.is(tok::equal) &&
- DeclaratorInfo.isFunctionDeclarator() &&
+ DeclaratorInfo.isFunctionDeclarator() &&
NextToken().is(tok::numeric_constant)) {
EqualLoc = ConsumeToken();
Init = ParseInitializer();
@@ -2183,8 +2238,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
SkipUntil(tok::r_brace);
// Consume the optional ';'
- if (Tok.is(tok::semi))
- ConsumeToken();
+ TryConsumeToken(tok::semi);
+
return;
}
@@ -2222,40 +2277,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// member-declarator
// member-declarator-list ',' member-declarator
- SmallVector<Decl *, 8> DeclsInGroup;
- ExprResult BitfieldSize;
- bool ExpectSemi = true;
-
while (1) {
- // member-declarator:
- // declarator pure-specifier[opt]
- // declarator brace-or-equal-initializer[opt]
- // identifier[opt] ':' constant-expression
- if (Tok.is(tok::colon)) {
- ConsumeToken();
- BitfieldSize = ParseConstantExpression();
- if (BitfieldSize.isInvalid())
- SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
- }
-
- // If a simple-asm-expr is present, parse it.
- if (Tok.is(tok::kw_asm)) {
- SourceLocation Loc;
- ExprResult AsmLabel(ParseSimpleAsm(&Loc));
- if (AsmLabel.isInvalid())
- SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
-
- DeclaratorInfo.setAsmLabel(AsmLabel.release());
- DeclaratorInfo.SetRangeEnd(Loc);
- }
-
- // If attributes exist after the declarator, parse them.
- MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs);
-
- // FIXME: When g++ adds support for this, we'll need to check whether it
- // goes before or after the GNU attributes and __asm__.
- ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface);
-
InClassInitStyle HasInClassInit = ICIS_NoInit;
if ((Tok.is(tok::equal) || Tok.is(tok::l_brace)) && !HasInitializer) {
if (BitfieldSize.get()) {
@@ -2274,35 +2296,31 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// this call will *not* return the created decl; It will return null.
// See Sema::ActOnCXXMemberDeclarator for details.
- NamedDecl *ThisDecl = 0;
+ NamedDecl *ThisDecl = nullptr;
if (DS.isFriendSpecified()) {
- // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains
+ // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains
// to a friend declaration, that declaration shall be a definition.
//
- // Diagnose attributes appear after friend member function declarator:
- // foo [[]] ();
+ // Diagnose attributes that appear in a friend member function declarator:
+ // friend int foo [[]] ();
SmallVector<SourceRange, 4> Ranges;
DeclaratorInfo.getCXX11AttributeRanges(Ranges);
- if (!Ranges.empty()) {
- for (SmallVectorImpl<SourceRange>::iterator I = Ranges.begin(),
- E = Ranges.end(); I != E; ++I) {
- Diag((*I).getBegin(), diag::err_attributes_not_allowed)
- << *I;
- }
- }
+ for (SmallVectorImpl<SourceRange>::iterator I = Ranges.begin(),
+ E = Ranges.end(); I != E; ++I)
+ Diag((*I).getBegin(), diag::err_attributes_not_allowed) << *I;
- // TODO: handle initializers, bitfields, 'delete'
+ // TODO: handle initializers, VS, bitfields, 'delete'
ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo,
TemplateParams);
} else {
ThisDecl = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS,
DeclaratorInfo,
TemplateParams,
- BitfieldSize.release(),
+ BitfieldSize.get(),
VS, HasInClassInit);
if (VarTemplateDecl *VT =
- ThisDecl ? dyn_cast<VarTemplateDecl>(ThisDecl) : 0)
+ ThisDecl ? dyn_cast<VarTemplateDecl>(ThisDecl) : nullptr)
// Re-direct this decl to refer to the templated decl so that we can
// initialize it.
ThisDecl = VT->getTemplatedDecl();
@@ -2372,12 +2390,10 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// If we don't have a comma, it is either the end of the list (a ';')
// or an error, bail out.
- if (Tok.isNot(tok::comma))
+ SourceLocation CommaLoc;
+ if (!TryConsumeToken(tok::comma, CommaLoc))
break;
- // Consume the comma.
- SourceLocation CommaLoc = ConsumeToken();
-
if (Tok.isAtStartOfLine() &&
!MightBeDeclarator(Declarator::MemberContext)) {
// This comma was followed by a line-break and something which can't be
@@ -2397,11 +2413,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
HasInitializer = false;
DeclaratorInfo.setCommaLoc(CommaLoc);
- // Attributes are only allowed on the second declarator.
+ // GNU attributes are allowed before the second and subsequent declarator.
MaybeParseGNUAttributes(DeclaratorInfo);
- if (Tok.isNot(tok::colon))
- ParseDeclarator(DeclaratorInfo);
+ ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize,
+ LateParsedAttrs);
}
if (ExpectSemi &&
@@ -2409,7 +2425,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// Skip to end of block or statement.
SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
// If we stopped at a ';', eat it.
- if (Tok.is(tok::semi)) ConsumeToken();
+ TryConsumeToken(tok::semi);
return;
}
@@ -2446,8 +2462,7 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,
EnterExpressionEvaluationContext Context(Actions,
Sema::PotentiallyEvaluated,
D);
- if (Tok.is(tok::equal)) {
- EqualLoc = ConsumeToken();
+ if (TryConsumeToken(tok::equal, EqualLoc)) {
if (Tok.is(tok::kw_delete)) {
// In principle, an initializer of '= delete p;' is legal, but it will
// never type-check. It's better to diagnose it as an ill-formed expression
@@ -2456,13 +2471,13 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,
// 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)) {
+ Next.is(tok::eof)) {
if (IsFunction)
Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
<< 1 /* delete */;
else
Diag(ConsumeToken(), diag::err_deleted_non_function);
- return ExprResult();
+ return ExprError();
}
} else if (Tok.is(tok::kw_default)) {
if (IsFunction)
@@ -2470,7 +2485,7 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,
<< 0 /* default */;
else
Diag(ConsumeToken(), diag::err_default_special_members);
- return ExprResult();
+ return ExprError();
}
}
@@ -2510,7 +2525,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
<< /*ErrorType=*/6
<< (isa<NamedDecl>(TagDecl)
? cast<NamedDecl>(TagDecl)->getQualifiedNameAsString()
- : "<anonymous>");
+ : "(anonymous)");
}
break;
}
@@ -2601,7 +2616,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
if (TagDecl) {
// While we still have something to read, read the member-declarations.
- while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ 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) ||
@@ -2636,6 +2651,16 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
continue;
}
+ if (Tok.is(tok::annot_pragma_ms_pointers_to_members)) {
+ HandlePragmaMSPointersToMembers();
+ continue;
+ }
+
+ if (Tok.is(tok::annot_pragma_ms_pragma)) {
+ HandlePragmaMSPragma();
+ continue;
+ }
+
// If we see a namespace here, a close brace was missing somewhere.
if (Tok.is(tok::kw_namespace)) {
DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl));
@@ -2653,18 +2678,14 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
MaybeParseGNUAttributes(AccessAttrs);
SourceLocation EndLoc;
- if (Tok.is(tok::colon)) {
- EndLoc = Tok.getLocation();
- ConsumeToken();
- } else if (Tok.is(tok::semi)) {
- EndLoc = Tok.getLocation();
- ConsumeToken();
- Diag(EndLoc, diag::err_expected_colon)
- << FixItHint::CreateReplacement(EndLoc, ":");
+ if (TryConsumeToken(tok::colon, EndLoc)) {
+ } else if (TryConsumeToken(tok::semi, EndLoc)) {
+ Diag(EndLoc, diag::err_expected)
+ << tok::colon << FixItHint::CreateReplacement(EndLoc, ":");
} else {
EndLoc = ASLoc.getLocWithOffset(TokLength);
- Diag(EndLoc, diag::err_expected_colon)
- << FixItHint::CreateInsertion(EndLoc, ":");
+ Diag(EndLoc, diag::err_expected)
+ << tok::colon << FixItHint::CreateInsertion(EndLoc, ":");
}
// The Microsoft extension __interface does not permit non-public
@@ -2810,7 +2831,8 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {
<< FixItHint::CreateInsertion(Loc, ", ");
} else {
// Skip over garbage, until we get to '{'. Don't eat the '{'.
- Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma);
+ Diag(Tok.getLocation(), diag::err_expected_either) << tok::l_brace
+ << tok::comma;
SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);
break;
}
@@ -2854,7 +2876,7 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
return true;
}
- IdentifierInfo *II = 0;
+ IdentifierInfo *II = nullptr;
DeclSpec DS(AttrFactory);
SourceLocation IdLoc = Tok.getLocation();
if (Tok.is(tok::annot_decltype)) {
@@ -2878,12 +2900,11 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
return true;
SourceLocation EllipsisLoc;
- if (Tok.is(tok::ellipsis))
- EllipsisLoc = ConsumeToken();
+ TryConsumeToken(tok::ellipsis, EllipsisLoc);
return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,
TemplateTypeTy, DS, IdLoc,
- InitList.take(), EllipsisLoc);
+ InitList.get(), EllipsisLoc);
} else if(Tok.is(tok::l_paren)) {
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
@@ -2899,8 +2920,7 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
T.consumeClose();
SourceLocation EllipsisLoc;
- if (Tok.is(tok::ellipsis))
- EllipsisLoc = ConsumeToken();
+ TryConsumeToken(tok::ellipsis, EllipsisLoc);
return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,
TemplateTypeTy, DS, IdLoc,
@@ -2908,9 +2928,10 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
T.getCloseLocation(), EllipsisLoc);
}
- Diag(Tok, getLangOpts().CPlusPlus11 ? diag::err_expected_lparen_or_lbrace
- : diag::err_expected_lparen);
- return true;
+ if (getLangOpts().CPlusPlus11)
+ return Diag(Tok, diag::err_expected_either) << tok::l_paren << tok::l_brace;
+ else
+ return Diag(Tok, diag::err_expected) << tok::l_paren;
}
/// \brief Parse a C++ exception-specification if present (C++0x [except.spec]).
@@ -3054,10 +3075,8 @@ ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification(
Exceptions.push_back(Res.get());
Ranges.push_back(Range);
}
-
- if (Tok.is(tok::comma))
- ConsumeToken();
- else
+
+ if (!TryConsumeToken(tok::comma))
break;
}
@@ -3153,7 +3172,7 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) {
Loc = ConsumeToken();
return II;
}
- return 0;
+ return nullptr;
case tok::ampamp: // 'and'
case tok::pipe: // 'bitor'
@@ -3174,7 +3193,7 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) {
Loc = ConsumeToken();
return &PP.getIdentifierTable().get(Spelling);
}
- return 0;
+ return nullptr;
}
}
@@ -3183,6 +3202,7 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
switch (AttributeList::getKind(AttrName, ScopeName,
AttributeList::AS_CXX11)) {
case AttributeList::AT_CarriesDependency:
+ case AttributeList::AT_Deprecated:
case AttributeList::AT_FallThrough:
case AttributeList::AT_CXX11NoReturn: {
return true;
@@ -3193,8 +3213,75 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
}
}
-/// ParseCXX11AttributeSpecifier - Parse a C++11 attribute-specifier. Currently
-/// only parses standard attributes.
+/// ParseCXX11AttributeArgs -- Parse a C++11 attribute-argument-clause.
+///
+/// [C++11] attribute-argument-clause:
+/// '(' balanced-token-seq ')'
+///
+/// [C++11] balanced-token-seq:
+/// balanced-token
+/// balanced-token-seq balanced-token
+///
+/// [C++11] balanced-token:
+/// '(' balanced-token-seq ')'
+/// '[' balanced-token-seq ']'
+/// '{' balanced-token-seq '}'
+/// any token but '(', ')', '[', ']', '{', or '}'
+bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs,
+ SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc) {
+ assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list");
+ SourceLocation LParenLoc = Tok.getLocation();
+
+ // If the attribute isn't known, we will not attempt to parse any
+ // arguments.
+ if (!hasAttribute(AttrSyntax::CXX, ScopeName, AttrName,
+ getTargetInfo().getTriple(), getLangOpts())) {
+ // Eat the left paren, then skip to the ending right paren.
+ ConsumeParen();
+ SkipUntil(tok::r_paren);
+ return false;
+ }
+
+ if (ScopeName && ScopeName->getName() == "gnu")
+ // GNU-scoped attributes have some special cases to handle GNU-specific
+ // behaviors.
+ ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
+ ScopeLoc, AttributeList::AS_CXX11, nullptr);
+ else {
+ unsigned NumArgs =
+ ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
+ ScopeName, ScopeLoc, AttributeList::AS_CXX11);
+
+ const AttributeList *Attr = Attrs.getList();
+ if (Attr && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) {
+ // If the attribute is a standard or built-in attribute and we are
+ // parsing an argument list, we need to determine whether this attribute
+ // was allowed to have an argument list (such as [[deprecated]]), and how
+ // many arguments were parsed (so we can diagnose on [[deprecated()]]).
+ if (Attr->getMaxArgs() && !NumArgs) {
+ // The attribute was allowed to have arguments, but none were provided
+ // even though the attribute parsed successfully. This is an error.
+ // FIXME: This is a good place for a fixit which removes the parens.
+ 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
+ // presence of the argument list (even if empty) is diagnosed.
+ Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments)
+ << AttrName;
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+/// ParseCXX11AttributeSpecifier - Parse a C++11 attribute-specifier.
///
/// [C++11] attribute-specifier:
/// '[' '[' attribute-list ']' ']'
@@ -3218,19 +3305,6 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
///
/// [C++11] attribute-namespace:
/// identifier
-///
-/// [C++11] attribute-argument-clause:
-/// '(' balanced-token-seq ')'
-///
-/// [C++11] balanced-token-seq:
-/// balanced-token
-/// balanced-token-seq balanced-token
-///
-/// [C++11] balanced-token:
-/// '(' balanced-token-seq ')'
-/// '[' balanced-token-seq ']'
-/// '{' balanced-token-seq '}'
-/// any token but '(', ')', '[', ']', '{', or '}'
void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
SourceLocation *endLoc) {
if (Tok.is(tok::kw_alignas)) {
@@ -3251,13 +3325,11 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
while (Tok.isNot(tok::r_square)) {
// attribute not present
- if (Tok.is(tok::comma)) {
- ConsumeToken();
+ if (TryConsumeToken(tok::comma))
continue;
- }
SourceLocation ScopeLoc, AttrLoc;
- IdentifierInfo *ScopeName = 0, *AttrName = 0;
+ IdentifierInfo *ScopeName = nullptr, *AttrName = nullptr;
AttrName = TryParseCXX11AttributeIdentifier(AttrLoc);
if (!AttrName)
@@ -3265,64 +3337,47 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
break;
// scoped attribute
- if (Tok.is(tok::coloncolon)) {
- ConsumeToken();
-
+ if (TryConsumeToken(tok::coloncolon)) {
ScopeName = AttrName;
ScopeLoc = AttrLoc;
AttrName = TryParseCXX11AttributeIdentifier(AttrLoc);
if (!AttrName) {
- Diag(Tok.getLocation(), diag::err_expected_ident);
+ Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
SkipUntil(tok::r_square, tok::comma, StopAtSemi | StopBeforeMatch);
continue;
}
}
- bool StandardAttr = IsBuiltInOrStandardCXX11Attribute(AttrName,ScopeName);
+ bool StandardAttr = IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName);
bool AttrParsed = false;
if (StandardAttr &&
!SeenAttrs.insert(std::make_pair(AttrName, AttrLoc)).second)
Diag(AttrLoc, diag::err_cxx11_attribute_repeated)
- << AttrName << SourceRange(SeenAttrs[AttrName]);
+ << AttrName << SourceRange(SeenAttrs[AttrName]);
// Parse attribute arguments
- if (Tok.is(tok::l_paren)) {
- if (ScopeName && ScopeName->getName() == "gnu") {
- ParseGNUAttributeArgs(AttrName, AttrLoc, attrs, endLoc,
- ScopeName, ScopeLoc, AttributeList::AS_CXX11);
- AttrParsed = true;
- } else {
- if (StandardAttr)
- Diag(Tok.getLocation(), diag::err_cxx11_attribute_forbids_arguments)
- << AttrName->getName();
-
- // FIXME: handle other formats of c++11 attribute arguments
- ConsumeParen();
- SkipUntil(tok::r_paren);
- }
- }
+ if (Tok.is(tok::l_paren))
+ AttrParsed = ParseCXX11AttributeArgs(AttrName, AttrLoc, attrs, endLoc,
+ ScopeName, ScopeLoc);
if (!AttrParsed)
attrs.addNew(AttrName,
SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc,
AttrLoc),
- ScopeName, ScopeLoc, 0, 0, AttributeList::AS_CXX11);
-
- if (Tok.is(tok::ellipsis)) {
- ConsumeToken();
+ ScopeName, ScopeLoc, nullptr, 0, AttributeList::AS_CXX11);
+ if (TryConsumeToken(tok::ellipsis))
Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis)
<< AttrName->getName();
- }
}
- if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
+ if (ExpectAndConsume(tok::r_square))
SkipUntil(tok::r_square);
if (endLoc)
*endLoc = Tok.getLocation();
- if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
+ if (ExpectAndConsume(tok::r_square))
SkipUntil(tok::r_square);
}
@@ -3346,13 +3401,23 @@ void Parser::ParseCXX11Attributes(ParsedAttributesWithRange &attrs,
}
void Parser::DiagnoseAndSkipCXX11Attributes() {
- if (!isCXX11AttributeSpecifier())
- return;
-
// Start and end location of an attribute or an attribute list.
SourceLocation StartLoc = Tok.getLocation();
+ SourceLocation EndLoc = SkipCXX11Attributes();
+
+ if (EndLoc.isValid()) {
+ SourceRange Range(StartLoc, EndLoc);
+ Diag(StartLoc, diag::err_attributes_not_allowed)
+ << Range;
+ }
+}
+
+SourceLocation Parser::SkipCXX11Attributes() {
SourceLocation EndLoc;
+ if (!isCXX11AttributeSpecifier())
+ return EndLoc;
+
do {
if (Tok.is(tok::l_square)) {
BalancedDelimiterTracker T(*this, tok::l_square);
@@ -3369,11 +3434,7 @@ void Parser::DiagnoseAndSkipCXX11Attributes() {
}
} while (isCXX11AttributeSpecifier());
- if (EndLoc.isValid()) {
- SourceRange Range(StartLoc, EndLoc);
- Diag(StartLoc, diag::err_attributes_not_allowed)
- << Range;
- }
+ return EndLoc;
}
/// ParseMicrosoftAttributes - Parse a Microsoft attribute [Attr]
@@ -3393,7 +3454,7 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs,
ConsumeBracket();
SkipUntil(tok::r_square, StopAtSemi | StopBeforeMatch);
if (endLoc) *endLoc = Tok.getLocation();
- ExpectAndConsume(tok::r_square, diag::err_expected_rsquare);
+ ExpectAndConsume(tok::r_square);
}
}
@@ -3405,7 +3466,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
BalancedDelimiterTracker Braces(*this, tok::l_brace);
if (Braces.consumeOpen()) {
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
return;
}
@@ -3424,7 +3485,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
return;
}
- while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ 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))) {
ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS);
@@ -3446,13 +3507,13 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
if (Tok.is(tok::colon))
Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation());
else
- Diag(Tok, diag::err_expected_colon);
+ Diag(Tok, diag::err_expected) << tok::colon;
ConsumeToken();
continue;
}
// Parse all the comma separated declarators.
- ParseCXXClassMemberDeclaration(CurAS, 0);
+ ParseCXXClassMemberDeclaration(CurAS, nullptr);
}
Braces.consumeClose();
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 45f1b1da2e7f..0e4dfb91ad5d 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -23,6 +23,7 @@
#include "clang/Parse/Parser.h"
#include "RAIIObjectsForParser.h"
+#include "clang/AST/ASTContext.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
@@ -147,7 +148,7 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) {
if (!LHS.isInvalid())
LHS = Actions.ActOnUnaryOp(getCurScope(), ExtLoc, tok::kw___extension__,
- LHS.take());
+ LHS.get());
return ParseRHSOfBinaryExpression(LHS, prec::Comma);
}
@@ -260,19 +261,16 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
TernaryMiddle = ParseExpression();
if (TernaryMiddle.isInvalid()) {
LHS = ExprError();
- TernaryMiddle = 0;
+ TernaryMiddle = nullptr;
}
} else {
// Special case handling of "X ? Y : Z" where Y is empty:
// logical-OR-expression '?' ':' conditional-expression [GNU]
- TernaryMiddle = 0;
+ TernaryMiddle = nullptr;
Diag(Tok, diag::ext_gnu_conditional_expr);
}
- if (Tok.is(tok::colon)) {
- // Eat the colon.
- ColonLoc = ConsumeToken();
- } else {
+ if (!TryConsumeToken(tok::colon, ColonLoc)) {
// Otherwise, we're missing a ':'. Assume that this was a typo that
// the user forgot. If we're not in a macro expansion, we can suggest
// a fixit hint. If there were two spaces before the current token,
@@ -294,10 +292,10 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
}
}
}
-
- Diag(Tok, diag::err_expected_colon)
- << FixItHint::CreateInsertion(FILoc, FIText);
- Diag(OpToken, diag::note_matching) << "?";
+
+ Diag(Tok, diag::err_expected)
+ << tok::colon << FixItHint::CreateInsertion(FILoc, FIText);
+ Diag(OpToken, diag::note_matching) << tok::question;
ColonLoc = Tok.getLocation();
}
}
@@ -394,11 +392,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
Actions.getExprRange(RHS.get()).getEnd()));
LHS = Actions.ActOnBinOp(getCurScope(), OpToken.getLocation(),
- OpToken.getKind(), LHS.take(), RHS.take());
+ OpToken.getKind(), LHS.get(), RHS.get());
} else
LHS = Actions.ActOnConditionalOp(OpToken.getLocation(), ColonLoc,
- LHS.take(), TernaryMiddle.take(),
- RHS.take());
+ LHS.get(), TernaryMiddle.get(),
+ RHS.get());
}
}
}
@@ -430,14 +428,15 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
WantTypeSpecifiers = AllowTypes;
}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
NamedDecl *ND = candidate.getCorrectionDecl();
if (!ND)
return candidate.isKeyword();
if (isa<TypeDecl>(ND))
return WantTypeSpecifiers;
- return AllowNonTypes;
+ return AllowNonTypes &&
+ CorrectionCandidateCallback::ValidateCandidate(candidate);
}
private:
@@ -639,18 +638,12 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// If this expression is limited to being a unary-expression, the parent can
// not start a cast expression.
ParenParseOption ParenExprType =
- (isUnaryExpression && !getLangOpts().CPlusPlus)? CompoundLiteral : CastExpr;
+ (isUnaryExpression && !getLangOpts().CPlusPlus) ? CompoundLiteral
+ : CastExpr;
ParsedType CastTy;
SourceLocation RParenLoc;
-
- {
- // The inside of the parens don't need to be a colon protected scope, and
- // isn't immediately a message send.
- ColonProtectionRAIIObject X(*this, false);
-
- Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
- isTypeCast == IsTypeCast, CastTy, RParenLoc);
- }
+ Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
+ isTypeCast == IsTypeCast, CastTy, RParenLoc);
switch (ParenExprType) {
case SimpleExpr: break; // Nothing else to do.
@@ -690,7 +683,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return Actions.ActOnCXXNullPtrLiteral(ConsumeToken());
case tok::annot_primary_expr:
- assert(Res.get() == 0 && "Stray primary-expression annotation?");
+ assert(Res.get() == nullptr && "Stray primary-expression annotation?");
Res = getExprAnnotation(Tok);
ConsumeToken();
break;
@@ -715,48 +708,11 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// If this identifier was reverted from a token ID, and the next token
// is a parenthesis, this is likely to be a use of a type trait. Check
// those tokens.
- if (Next.is(tok::l_paren) &&
- Tok.is(tok::identifier) &&
- Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier()) {
- IdentifierInfo *II = Tok.getIdentifierInfo();
- // Build up the mapping of revertable type traits, for future use.
- if (RevertableTypeTraits.empty()) {
-#define RTT_JOIN(X,Y) X##Y
-#define REVERTABLE_TYPE_TRAIT(Name) \
- RevertableTypeTraits[PP.getIdentifierInfo(#Name)] \
- = RTT_JOIN(tok::kw_,Name)
-
- REVERTABLE_TYPE_TRAIT(__is_arithmetic);
- REVERTABLE_TYPE_TRAIT(__is_convertible);
- REVERTABLE_TYPE_TRAIT(__is_empty);
- REVERTABLE_TYPE_TRAIT(__is_floating_point);
- REVERTABLE_TYPE_TRAIT(__is_function);
- REVERTABLE_TYPE_TRAIT(__is_fundamental);
- REVERTABLE_TYPE_TRAIT(__is_integral);
- REVERTABLE_TYPE_TRAIT(__is_member_function_pointer);
- REVERTABLE_TYPE_TRAIT(__is_member_pointer);
- REVERTABLE_TYPE_TRAIT(__is_pod);
- REVERTABLE_TYPE_TRAIT(__is_pointer);
- REVERTABLE_TYPE_TRAIT(__is_same);
- REVERTABLE_TYPE_TRAIT(__is_scalar);
- REVERTABLE_TYPE_TRAIT(__is_signed);
- REVERTABLE_TYPE_TRAIT(__is_unsigned);
- REVERTABLE_TYPE_TRAIT(__is_void);
-#undef REVERTABLE_TYPE_TRAIT
-#undef RTT_JOIN
- }
-
- // If we find that this is in fact the name of a type trait,
- // update the token kind in place and parse again to treat it as
- // the appropriate kind of type trait.
- llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind>::iterator Known
- = RevertableTypeTraits.find(II);
- if (Known != RevertableTypeTraits.end()) {
- Tok.setKind(Known->second);
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
- NotCastExpr, isTypeCast);
- }
- }
+ if (Next.is(tok::l_paren) && Tok.is(tok::identifier) &&
+ Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier() &&
+ TryIdentKeywordUpgrade())
+ return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
+ NotCastExpr, isTypeCast);
if (Next.is(tok::coloncolon) ||
(!ColonIsSacred && Next.is(tok::colon)) ||
@@ -806,8 +762,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
((Tok.is(tok::identifier) &&
(NextToken().is(tok::colon) || NextToken().is(tok::r_square))) ||
Tok.is(tok::code_completion))) {
- Res = ParseObjCMessageExpressionBody(SourceLocation(), ILoc, ParsedType(),
- 0);
+ Res = ParseObjCMessageExpressionBody(SourceLocation(), ILoc, ParsedType(),
+ nullptr);
break;
}
@@ -828,19 +784,20 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
DeclSpec DS(AttrFactory);
DS.SetRangeStart(ILoc);
DS.SetRangeEnd(ILoc);
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
- DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ);
+ DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ,
+ Actions.getASTContext().getPrintingPolicy());
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
TypeResult Ty = Actions.ActOnTypeName(getCurScope(),
DeclaratorInfo);
if (Ty.isInvalid())
break;
-
+
Res = ParseObjCMessageExpressionBody(SourceLocation(),
SourceLocation(),
- Ty.get(), 0);
+ Ty.get(), nullptr);
break;
}
}
@@ -857,6 +814,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
SourceLocation TemplateKWLoc;
CastExpressionIdValidator Validator(isTypeCast != NotTypeCast,
isTypeCast != IsTypeCast);
+ Validator.IsAddressOfOperand = isAddressOfOperand;
Name.setIdentifier(&II, ILoc);
Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec, TemplateKWLoc,
Name, Tok.is(tok::l_paren),
@@ -873,6 +831,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
case tok::kw___FUNCDNAME__: // primary-expression: __FUNCDNAME__ [MS]
+ case tok::kw___FUNCSIG__: // primary-expression: __FUNCSIG__ [MS]
case tok::kw_L__FUNCTION__: // primary-expression: L__FUNCTION__ [MS]
case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);
@@ -904,7 +863,12 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// ++ cast-expression
// -- cast-expression
SourceLocation SavedLoc = ConsumeToken();
- Res = ParseCastExpression(!getLangOpts().CPlusPlus);
+ // One special case is implicitly handled here: if the preceding tokens are
+ // an ambiguous cast expression, such as "(T())++", then we recurse to
+ // determine whether the '++' is prefix or postfix.
+ Res = ParseCastExpression(!getLangOpts().CPlusPlus,
+ /*isAddressOfOperand*/false, NotCastExpr,
+ NotTypeCast);
if (!Res.isInvalid())
Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
return Res;
@@ -955,9 +919,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::ampamp: { // unary-expression: '&&' identifier
SourceLocation AmpAmpLoc = ConsumeToken();
if (Tok.isNot(tok::identifier))
- return ExprError(Diag(Tok, diag::err_expected_ident));
+ return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);
- if (getCurScope()->getFnParent() == 0)
+ if (getCurScope()->getFnParent() == nullptr)
return ExprError(Diag(Tok, diag::err_address_of_label_outside_fn));
Diag(AmpAmpLoc, diag::ext_gnu_address_of_label);
@@ -992,10 +956,11 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
DS.SetRangeStart(Tok.getLocation());
DS.SetRangeEnd(Tok.getLastLoc());
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
DS.SetTypeSpecType(TST_typename, Tok.getAnnotationEndLoc(),
- PrevSpec, DiagID, Type);
+ PrevSpec, DiagID, Type,
+ Actions.getASTContext().getPrintingPolicy());
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
@@ -1004,7 +969,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
ConsumeToken();
Res = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(),
- Ty.get(), 0);
+ Ty.get(), nullptr);
break;
}
// Fall through
@@ -1028,15 +993,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw_void:
case tok::kw_typename:
case tok::kw_typeof:
- case tok::kw___vector:
- case tok::kw_image1d_t:
- case tok::kw_image1d_array_t:
- case tok::kw_image1d_buffer_t:
- case tok::kw_image2d_t:
- case tok::kw_image2d_array_t:
- case tok::kw_image3d_t:
- case tok::kw_sampler_t:
- case tok::kw_event_t: {
+ case tok::kw___vector: {
if (!getLangOpts().CPlusPlus) {
Diag(Tok, diag::err_expected_expression);
return ExprError();
@@ -1164,69 +1121,13 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
if (!Result.isInvalid())
Result = Actions.ActOnNoexceptExpr(KeyLoc, T.getOpenLocation(),
- Result.take(), T.getCloseLocation());
+ Result.get(), T.getCloseLocation());
return Result;
}
- case tok::kw___is_abstract: // [GNU] unary-type-trait
- case tok::kw___is_class:
- case tok::kw___is_empty:
- case tok::kw___is_enum:
- case tok::kw___is_interface_class:
- case tok::kw___is_literal:
- case tok::kw___is_arithmetic:
- case tok::kw___is_integral:
- case tok::kw___is_floating_point:
- case tok::kw___is_complete_type:
- case tok::kw___is_void:
- case tok::kw___is_array:
- case tok::kw___is_function:
- case tok::kw___is_reference:
- case tok::kw___is_lvalue_reference:
- case tok::kw___is_rvalue_reference:
- case tok::kw___is_fundamental:
- case tok::kw___is_object:
- case tok::kw___is_scalar:
- case tok::kw___is_compound:
- case tok::kw___is_pointer:
- case tok::kw___is_member_object_pointer:
- case tok::kw___is_member_function_pointer:
- case tok::kw___is_member_pointer:
- case tok::kw___is_const:
- case tok::kw___is_volatile:
- case tok::kw___is_standard_layout:
- case tok::kw___is_signed:
- case tok::kw___is_unsigned:
- case tok::kw___is_literal_type:
- case tok::kw___is_pod:
- case tok::kw___is_polymorphic:
- case tok::kw___is_trivial:
- case tok::kw___is_trivially_copyable:
- case tok::kw___is_union:
- case tok::kw___is_final:
- case tok::kw___is_sealed:
- case tok::kw___has_trivial_constructor:
- case tok::kw___has_trivial_move_constructor:
- case tok::kw___has_trivial_copy:
- case tok::kw___has_trivial_assign:
- case tok::kw___has_trivial_move_assign:
- case tok::kw___has_trivial_destructor:
- case tok::kw___has_nothrow_assign:
- case tok::kw___has_nothrow_move_assign:
- case tok::kw___has_nothrow_copy:
- case tok::kw___has_nothrow_constructor:
- case tok::kw___has_virtual_destructor:
- return ParseUnaryTypeTrait();
-
- case tok::kw___builtin_types_compatible_p:
- case tok::kw___is_base_of:
- case tok::kw___is_same:
- case tok::kw___is_convertible:
- case tok::kw___is_convertible_to:
- case tok::kw___is_trivially_assignable:
- return ParseBinaryTypeTrait();
-
- case tok::kw___is_trivially_constructible:
+#define TYPE_TRAIT(N,Spelling,K) \
+ case tok::kw_##Spelling:
+#include "clang/Basic/TokenKinds.def"
return ParseTypeTrait();
case tok::kw___array_rank:
@@ -1358,8 +1259,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
SourceLocation RLoc = Tok.getLocation();
if (!LHS.isInvalid() && !Idx.isInvalid() && Tok.is(tok::r_square)) {
- LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.take(), Loc,
- Idx.take(), RLoc);
+ LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.get(), Loc,
+ Idx.get(), RLoc);
} else
LHS = ExprError();
@@ -1373,8 +1274,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
// '(' argument-expression-list[opt] ')'
tok::TokenKind OpKind = Tok.getKind();
InMessageExpressionRAIIObject InMessage(*this, false);
-
- Expr *ExecConfig = 0;
+
+ Expr *ExecConfig = nullptr;
BalancedDelimiterTracker PT(*this, tok::l_paren);
@@ -1387,21 +1288,20 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
LHS = ExprError();
}
- SourceLocation CloseLoc = Tok.getLocation();
- if (Tok.is(tok::greatergreatergreater)) {
- ConsumeToken();
+ SourceLocation CloseLoc;
+ if (TryConsumeToken(tok::greatergreatergreater, CloseLoc)) {
} else if (LHS.isInvalid()) {
SkipUntil(tok::greatergreatergreater, StopAtSemi);
} else {
// There was an error closing the brackets
- Diag(Tok, diag::err_expected_ggg);
- Diag(OpenLoc, diag::note_matching) << "<<<";
+ Diag(Tok, diag::err_expected) << tok::greatergreatergreater;
+ Diag(OpenLoc, diag::note_matching) << tok::lesslessless;
SkipUntil(tok::greatergreatergreater, StopAtSemi);
LHS = ExprError();
}
if (!LHS.isInvalid()) {
- if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen, ""))
+ if (ExpectAndConsume(tok::l_paren))
LHS = ExprError();
else
Loc = PrevTokLocation;
@@ -1450,7 +1350,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
assert((ArgExprs.size() == 0 ||
ArgExprs.size()-1 == CommaLocs.size())&&
"Unexpected number of commas!");
- LHS = Actions.ActOnCallExpr(getCurScope(), LHS.take(), Loc,
+ LHS = Actions.ActOnCallExpr(getCurScope(), LHS.get(), Loc,
ArgExprs, Tok.getLocation(),
ExecConfig);
PT.consumeClose();
@@ -1469,14 +1369,14 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
ParsedType ObjectType;
bool MayBePseudoDestructor = false;
if (getLangOpts().CPlusPlus && !LHS.isInvalid()) {
- Expr *Base = LHS.take();
+ Expr *Base = LHS.get();
const Type* BaseType = Base->getType().getTypePtrOrNull();
if (BaseType && Tok.is(tok::l_paren) &&
(BaseType->isFunctionType() ||
BaseType->isSpecificPlaceholderType(BuiltinType::BoundMember))) {
Diag(OpLoc, diag::err_function_is_not_record)
- << (OpKind == tok::arrow) << Base->getSourceRange()
- << FixItHint::CreateRemoval(OpLoc);
+ << OpKind << Base->getSourceRange()
+ << FixItHint::CreateRemoval(OpLoc);
return ParsePostfixExpressionSuffix(Base);
}
@@ -1503,7 +1403,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
}
if (MayBePseudoDestructor && !LHS.isInvalid()) {
- LHS = ParseCXXPseudoDestructor(LHS.take(), OpLoc, OpKind, SS,
+ LHS = ParseCXXPseudoDestructor(LHS.get(), OpLoc, OpKind, SS,
ObjectType);
break;
}
@@ -1537,9 +1437,10 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
LHS = ExprError();
if (!LHS.isInvalid())
- LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.take(), OpLoc,
+ LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc,
OpKind, SS, TemplateKWLoc, Name,
- CurParsedObjCImpl ? CurParsedObjCImpl->Dcl : 0,
+ CurParsedObjCImpl ? CurParsedObjCImpl->Dcl
+ : nullptr,
Tok.is(tok::l_paren));
break;
}
@@ -1547,7 +1448,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
case tok::minusminus: // postfix-expression: postfix-expression '--'
if (!LHS.isInvalid()) {
LHS = Actions.ActOnPostfixUnaryOp(getCurScope(), Tok.getLocation(),
- Tok.getKind(), LHS.take());
+ Tok.getKind(), LHS.get());
}
ConsumeToken();
break;
@@ -1597,8 +1498,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
// 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)) {
- bool isAmbiguousTypeId;
- if (isTypeIdInParens(isAmbiguousTypeId)) {
+ if (isTypeIdUnambiguously()) {
DeclSpec DS(AttrFactory);
ParseSpecifierQualifierList(DS);
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
@@ -1617,7 +1517,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
isCastExpr = false;
if (OpTok.is(tok::kw_typeof) && !getLangOpts().CPlusPlus) {
- Diag(Tok,diag::err_expected_lparen_after_id) << OpTok.getIdentifierInfo();
+ Diag(Tok, diag::err_expected_after) << OpTok.getIdentifierInfo()
+ << tok::l_paren;
return ExprError();
}
@@ -1681,7 +1582,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
if (Tok.is(tok::ellipsis) && OpTok.is(tok::kw_sizeof)) {
SourceLocation EllipsisLoc = ConsumeToken();
SourceLocation LParenLoc, RParenLoc;
- IdentifierInfo *Name = 0;
+ IdentifierInfo *Name = nullptr;
SourceLocation NameLoc;
if (Tok.is(tok::l_paren)) {
BalancedDelimiterTracker T(*this, tok::l_paren);
@@ -1759,7 +1660,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
Operand = Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(),
ExprKind,
/*isType=*/false,
- Operand.release(),
+ Operand.get(),
CastRange);
return Operand;
}
@@ -1789,8 +1690,8 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
// All of these start with an open paren.
if (Tok.isNot(tok::l_paren))
- return ExprError(Diag(Tok, diag::err_expected_lparen_after_id)
- << BuiltinII);
+ return ExprError(Diag(Tok, diag::err_expected_after) << BuiltinII
+ << tok::l_paren);
BalancedDelimiterTracker PT(*this, tok::l_paren);
PT.consumeOpen();
@@ -1802,20 +1703,22 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
case tok::kw___builtin_va_arg: {
ExprResult Expr(ParseAssignmentExpression());
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
Expr = ExprError();
+ }
TypeResult Ty = ParseTypeName();
if (Tok.isNot(tok::r_paren)) {
- Diag(Tok, diag::err_expected_rparen);
+ Diag(Tok, diag::err_expected) << tok::r_paren;
Expr = ExprError();
}
if (Expr.isInvalid() || Ty.isInvalid())
Res = ExprError();
else
- Res = Actions.ActOnVAArg(StartLoc, Expr.take(), Ty.get(), ConsumeParen());
+ Res = Actions.ActOnVAArg(StartLoc, Expr.get(), Ty.get(), ConsumeParen());
break;
}
case tok::kw___builtin_offsetof: {
@@ -1826,12 +1729,14 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
return ExprError();
}
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
+ }
// We must have at least one identifier here.
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
@@ -1853,7 +1758,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
Comps.back().LocStart = ConsumeToken();
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
@@ -1875,7 +1780,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
SkipUntil(tok::r_paren, StopAtSemi);
return Res;
}
- Comps.back().U.E = Res.release();
+ Comps.back().U.E = Res.get();
ST.consumeClose();
Comps.back().LocEnd = ST.getCloseLocation();
@@ -1902,16 +1807,20 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
SkipUntil(tok::r_paren, StopAtSemi);
return Cond;
}
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
+ }
ExprResult Expr1(ParseAssignmentExpression());
if (Expr1.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
return Expr1;
}
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
+ }
ExprResult Expr2(ParseAssignmentExpression());
if (Expr2.isInvalid()) {
@@ -1919,11 +1828,11 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
return Expr2;
}
if (Tok.isNot(tok::r_paren)) {
- Diag(Tok, diag::err_expected_rparen);
+ Diag(Tok, diag::err_expected) << tok::r_paren;
return ExprError();
}
- Res = Actions.ActOnChooseExpr(StartLoc, Cond.take(), Expr1.take(),
- Expr2.take(), ConsumeParen());
+ Res = Actions.ActOnChooseExpr(StartLoc, Cond.get(), Expr1.get(),
+ Expr2.get(), ConsumeParen());
break;
}
case tok::kw___builtin_astype: {
@@ -1933,11 +1842,12 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
-
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",
- tok::r_paren))
+
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
-
+ }
+
// Second argument is the type to bitcast to.
TypeResult DestTy = ParseTypeName();
if (DestTy.isInvalid())
@@ -1945,12 +1855,12 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
// Attempt to consume the r-paren.
if (Tok.isNot(tok::r_paren)) {
- Diag(Tok, diag::err_expected_rparen);
+ Diag(Tok, diag::err_expected) << tok::r_paren;
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
- Res = Actions.ActOnAsTypeExpr(Expr.take(), DestTy.get(), StartLoc,
+ Res = Actions.ActOnAsTypeExpr(Expr.get(), DestTy.get(), StartLoc,
ConsumeParen());
break;
}
@@ -1961,11 +1871,12 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
-
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",
- tok::r_paren))
+
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
-
+ }
+
// Second argument is the type to bitcast to.
TypeResult DestTy = ParseTypeName();
if (DestTy.isInvalid())
@@ -1973,12 +1884,12 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
// Attempt to consume the r-paren.
if (Tok.isNot(tok::r_paren)) {
- Diag(Tok, diag::err_expected_rparen);
+ Diag(Tok, diag::err_expected) << tok::r_paren;
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
- Res = Actions.ActOnConvertVectorExpr(Expr.take(), DestTy.get(), StartLoc,
+ Res = Actions.ActOnConvertVectorExpr(Expr.get(), DestTy.get(), StartLoc,
ConsumeParen());
break;
}
@@ -1989,7 +1900,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
// These can be followed by postfix-expr pieces because they are
// primary-expressions.
- return ParsePostfixExpressionSuffix(Res.take());
+ return ParsePostfixExpressionSuffix(Res.get());
}
/// ParseParenExpression - This parses the unit that starts with a '(' token,
@@ -2018,6 +1929,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
bool isTypeCast, ParsedType &CastTy,
SourceLocation &RParenLoc) {
assert(Tok.is(tok::l_paren) && "Not a paren expr!");
+ ColonProtectionRAIIObject ColonProtection(*this, false);
BalancedDelimiterTracker T(*this, tok::l_paren);
if (T.consumeOpen())
return ExprError();
@@ -2042,7 +1954,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
Tok.is(tok::kw___bridge_retained) ||
Tok.is(tok::kw___bridge_retain)));
if (BridgeCast && !getLangOpts().ObjCAutoRefCount) {
- if (Tok.isNot(tok::kw___bridge)) {
+ if (!TryConsumeToken(tok::kw___bridge)) {
StringRef BridgeCastName = Tok.getName();
SourceLocation BridgeKeywordLoc = ConsumeToken();
if (!PP.getSourceManager().isInSystemHeader(BridgeKeywordLoc))
@@ -2050,8 +1962,6 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
<< BridgeCastName
<< FixItHint::CreateReplacement(BridgeKeywordLoc, "");
}
- else
- ConsumeToken(); // consume __bridge
BridgeCast = false;
}
@@ -2066,7 +1976,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// If the substmt parsed correctly, build the AST node.
if (!Stmt.isInvalid()) {
- Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.take(), Tok.getLocation());
+ Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.get(), Tok.getLocation());
} else {
Actions.ActOnStmtExprError();
}
@@ -2095,6 +2005,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
TypeResult Ty = ParseTypeName();
T.consumeClose();
+ ColonProtection.restore();
RParenLoc = T.getCloseLocation();
ExprResult SubExpr = ParseCastExpression(/*isUnaryExpression=*/false);
@@ -2115,7 +2026,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// if stopIfCastExpr is false, we need to determine the context past the
// parens, so we defer to ParseCXXAmbiguousParenExpression for that.
if (isAmbiguousTypeId && !stopIfCastExpr) {
- ExprResult res = ParseCXXAmbiguousParenExpression(ExprType, CastTy, T);
+ ExprResult res = ParseCXXAmbiguousParenExpression(ExprType, CastTy, T,
+ ColonProtection);
RParenLoc = T.getCloseLocation();
return res;
}
@@ -2139,10 +2051,11 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
}
Result = ParseObjCMessageExpressionBody(SourceLocation(),
SourceLocation(),
- Ty.get(), 0);
+ Ty.get(), nullptr);
} else {
// Match the ')'.
T.consumeClose();
+ ColonProtection.restore();
RParenLoc = T.getCloseLocation();
if (Tok.is(tok::l_brace)) {
ExprType = CompoundLiteral;
@@ -2171,7 +2084,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
CastTy = Ty.get();
return ExprResult();
}
-
+
// Reject the cast of super idiom in ObjC.
if (Tok.is(tok::identifier) && getLangOpts().ObjC1 &&
Tok.getIdentifierInfo() == Ident_super &&
@@ -2190,7 +2103,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
if (!Result.isInvalid()) {
Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc,
DeclaratorInfo, CastTy,
- RParenLoc, Result.take());
+ RParenLoc, Result.get());
}
return Result;
}
@@ -2218,7 +2131,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// Don't build a paren expression unless we actually match a ')'.
if (!Result.isInvalid() && Tok.is(tok::r_paren))
- Result = Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), Result.take());
+ Result =
+ Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), Result.get());
}
// Match the ')'.
@@ -2249,7 +2163,7 @@ Parser::ParseCompoundLiteralExpression(ParsedType Ty,
Diag(LParenLoc, diag::ext_c99_compound_literal);
ExprResult Result = ParseInitializer();
if (!Result.isInvalid() && Ty)
- return Actions.ActOnCompoundLiteral(LParenLoc, Ty, RParenLoc, Result.take());
+ return Actions.ActOnCompoundLiteral(LParenLoc, Ty, RParenLoc, Result.get());
return Result;
}
@@ -2274,8 +2188,9 @@ ExprResult Parser::ParseStringLiteralExpression(bool AllowUserDefinedLiteral) {
} while (isTokenStringLiteral());
// Pass the set of string tokens, ready for concatenation, to the actions.
- return Actions.ActOnStringLiteral(&StringToks[0], StringToks.size(),
- AllowUserDefinedLiteral ? getCurScope() : 0);
+ return Actions.ActOnStringLiteral(StringToks,
+ AllowUserDefinedLiteral ? getCurScope()
+ : nullptr);
}
/// ParseGenericSelectionExpression - Parse a C11 generic-selection
@@ -2299,7 +2214,7 @@ ExprResult Parser::ParseGenericSelectionExpression() {
Diag(KeyLoc, diag::ext_c11_generic_selection);
BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen))
+ if (T.expectAndConsume())
return ExprError();
ExprResult ControllingExpr;
@@ -2314,7 +2229,7 @@ ExprResult Parser::ParseGenericSelectionExpression() {
}
}
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "")) {
+ if (ExpectAndConsume(tok::comma)) {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
@@ -2322,7 +2237,7 @@ ExprResult Parser::ParseGenericSelectionExpression() {
SourceLocation DefaultLoc;
TypeVector Types;
ExprVector Exprs;
- while (1) {
+ do {
ParsedType Ty;
if (Tok.is(tok::kw_default)) {
// C11 6.5.1.1p2 "A generic selection shall have no more than one default
@@ -2342,11 +2257,11 @@ ExprResult Parser::ParseGenericSelectionExpression() {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
- Ty = TR.release();
+ Ty = TR.get();
}
Types.push_back(Ty);
- if (ExpectAndConsume(tok::colon, diag::err_expected_colon, "")) {
+ if (ExpectAndConsume(tok::colon)) {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
@@ -2358,12 +2273,8 @@ ExprResult Parser::ParseGenericSelectionExpression() {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
- Exprs.push_back(ER.release());
-
- if (Tok.isNot(tok::comma))
- break;
- ConsumeToken();
- }
+ Exprs.push_back(ER.get());
+ } while (TryConsumeToken(tok::comma));
T.consumeClose();
if (T.getCloseLocation().isInvalid())
@@ -2371,7 +2282,7 @@ ExprResult Parser::ParseGenericSelectionExpression() {
return Actions.ActOnGenericSelectionExpr(KeyLoc, DefaultLoc,
T.getCloseLocation(),
- ControllingExpr.release(),
+ ControllingExpr.get(),
Types, Exprs);
}
@@ -2403,6 +2314,7 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr*> &Exprs,
Expr *Data,
ArrayRef<Expr *> Args),
Expr *Data) {
+ bool SawError = false;
while (1) {
if (Tok.is(tok::code_completion)) {
if (Completer)
@@ -2422,13 +2334,15 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr*> &Exprs,
if (Tok.is(tok::ellipsis))
Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken());
- if (Expr.isInvalid())
- return true;
-
- Exprs.push_back(Expr.release());
+ if (Expr.isInvalid()) {
+ SkipUntil(tok::comma, tok::r_paren, StopBeforeMatch);
+ SawError = true;
+ } else {
+ Exprs.push_back(Expr.get());
+ }
if (Tok.isNot(tok::comma))
- return false;
+ return SawError;
// Move to the next argument, remember where the comma was.
CommaLocs.push_back(ConsumeToken());
}
@@ -2450,7 +2364,7 @@ Parser::ParseSimpleExpressionList(SmallVectorImpl<Expr*> &Exprs,
if (Expr.isInvalid())
return true;
- Exprs.push_back(Expr.release());
+ Exprs.push_back(Expr.get());
if (Tok.isNot(tok::comma))
return false;
@@ -2531,7 +2445,7 @@ ExprResult Parser::ParseBlockLiteralExpression() {
// SetIdentifier sets the source range end, but in this case we're past
// that location.
SourceLocation Tmp = ParamInfo.getSourceRange().getEnd();
- ParamInfo.SetIdentifier(0, CaretLoc);
+ ParamInfo.SetIdentifier(nullptr, CaretLoc);
ParamInfo.SetRangeEnd(Tmp);
if (ParamInfo.isInvalidType()) {
// If there was an error parsing the arguments, they may have
@@ -2554,7 +2468,7 @@ ExprResult Parser::ParseBlockLiteralExpression() {
ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/true,
/*IsAmbiguous=*/false,
/*RParenLoc=*/NoLoc,
- /*ArgInfo=*/0,
+ /*ArgInfo=*/nullptr,
/*NumArgs=*/0,
/*EllipsisLoc=*/NoLoc,
/*RParenLoc=*/NoLoc,
@@ -2566,10 +2480,10 @@ ExprResult Parser::ParseBlockLiteralExpression() {
/*MutableLoc=*/NoLoc,
EST_None,
/*ESpecLoc=*/NoLoc,
- /*Exceptions=*/0,
- /*ExceptionRanges=*/0,
+ /*Exceptions=*/nullptr,
+ /*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
- /*NoexceptExpr=*/0,
+ /*NoexceptExpr=*/nullptr,
CaretLoc, CaretLoc,
ParamInfo),
attrs, CaretLoc);
@@ -2592,7 +2506,7 @@ ExprResult Parser::ParseBlockLiteralExpression() {
StmtResult Stmt(ParseCompoundStatementBody());
BlockScope.Exit();
if (!Stmt.isInvalid())
- Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.take(), getCurScope());
+ Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.get(), getCurScope());
else
Actions.ActOnBlockError(CaretLoc, getCurScope());
return Result;
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 5fe47fc9711c..83121a8b1a2d 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -10,12 +10,13 @@
// This file implements the Expression parsing implementation for C++.
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/DeclTemplate.h"
-#include "clang/Parse/Parser.h"
+#include "clang/AST/ASTContext.h"
#include "RAIIObjectsForParser.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
@@ -26,7 +27,9 @@ using namespace clang;
static int SelectDigraphErrorMessage(tok::TokenKind Kind) {
switch (Kind) {
- case tok::kw_template: return 0;
+ // template name
+ case tok::unknown: return 0;
+ // casts
case tok::kw_const_cast: return 1;
case tok::kw_dynamic_cast: return 2;
case tok::kw_reinterpret_cast: return 3;
@@ -93,7 +96,7 @@ void Parser::CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectType,
Template, MemberOfUnknownSpecialization))
return;
- FixDigraph(*this, PP, Next, SecondToken, tok::kw_template,
+ FixDigraph(*this, PP, Next, SecondToken, tok::unknown,
/*AtDigraph*/false);
}
@@ -204,7 +207,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
}
if (LastII)
- *LastII = 0;
+ *LastII = nullptr;
bool HasScopeSpecifier = false;
@@ -233,12 +236,13 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
DeclSpec DS(AttrFactory);
SourceLocation DeclLoc = Tok.getLocation();
SourceLocation EndLoc = ParseDecltypeSpecifier(DS);
- if (Tok.isNot(tok::coloncolon)) {
+
+ SourceLocation CCLoc;
+ if (!TryConsumeToken(tok::coloncolon, CCLoc)) {
AnnotateExistingDecltypeSpecifier(DS, DeclLoc, EndLoc);
return false;
}
-
- SourceLocation CCLoc = ConsumeToken();
+
if (Actions.ActOnCXXNestedNameSpecifierDecltype(SS, DS, CCLoc))
SS.SetInvalid(SourceRange(DeclLoc, CCLoc));
@@ -287,19 +291,23 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
TentativeParsingAction TPA(*this);
SourceLocation TemplateKWLoc = ConsumeToken();
-
+
UnqualifiedId TemplateName;
if (Tok.is(tok::identifier)) {
// Consume the identifier.
TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
ConsumeToken();
} else if (Tok.is(tok::kw_operator)) {
- if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType,
+ // We don't need to actually parse the unqualified-id in this case,
+ // because a simple-template-id cannot start with 'operator', but
+ // go ahead and parse it anyway for consistency with the case where
+ // we already annotated the template-id.
+ if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType,
TemplateName)) {
TPA.Commit();
break;
}
-
+
if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId &&
TemplateName.getKind() != UnqualifiedId::IK_LiteralOperatorId) {
Diag(TemplateName.getSourceRange().getBegin(),
@@ -341,10 +349,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) {
// We have
//
- // simple-template-id '::'
+ // template-id '::'
//
- // So we need to check whether the simple-template-id is of the
- // right kind (it should name a type or be dependent), and then
+ // So we need to check whether the template-id is a simple-template-id of
+ // the right kind (it should name a type or be dependent), and then
// convert it into a type within the nested-name-specifier.
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
if (CheckForDestructor && GetLookAheadToken(2).is(tok::tilde)) {
@@ -357,15 +365,15 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// Consume the template-id token.
ConsumeToken();
-
+
assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
SourceLocation CCLoc = ConsumeToken();
HasScopeSpecifier = true;
-
+
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
TemplateId->NumArgs);
-
+
if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(),
SS,
TemplateId->TemplateKWLoc,
@@ -385,7 +393,6 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
continue;
}
-
// The rest of the nested-name-specifier possibilities start with
// tok::identifier.
if (Tok.isNot(tok::identifier))
@@ -410,9 +417,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// error, but they probably meant something else strange so don't
// recover like this.
PP.LookAhead(1).is(tok::identifier)) {
- Diag(Next, diag::err_unexected_colon_in_nested_name_spec)
+ Diag(Next, diag::err_unexpected_colon_in_nested_name_spec)
<< FixItHint::CreateReplacement(Next.getLocation(), "::");
-
// Recover as if the user wrote '::'.
Next.setKind(tok::coloncolon);
}
@@ -426,23 +432,52 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
return false;
}
+ if (ColonIsSacred) {
+ const Token &Next2 = GetLookAheadToken(2);
+ if (Next2.is(tok::kw_private) || Next2.is(tok::kw_protected) ||
+ Next2.is(tok::kw_public) || Next2.is(tok::kw_virtual)) {
+ Diag(Next2, diag::err_unexpected_token_in_nested_name_spec)
+ << Next2.getName()
+ << FixItHint::CreateReplacement(Next.getLocation(), ":");
+ Token ColonColon;
+ PP.Lex(ColonColon);
+ ColonColon.setKind(tok::colon);
+ PP.EnterToken(ColonColon);
+ break;
+ }
+ }
+
if (LastII)
*LastII = &II;
// We have an identifier followed by a '::'. Lookup this name
// as the name in a nested-name-specifier.
+ Token Identifier = Tok;
SourceLocation IdLoc = ConsumeToken();
assert((Tok.is(tok::coloncolon) || Tok.is(tok::colon)) &&
"NextToken() not working properly!");
+ Token ColonColon = Tok;
SourceLocation CCLoc = ConsumeToken();
CheckForLParenAfterColonColon();
- HasScopeSpecifier = true;
+ bool IsCorrectedToColon = false;
+ bool *CorrectionFlagPtr = ColonIsSacred ? &IsCorrectedToColon : nullptr;
if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), II, IdLoc, CCLoc,
- ObjectType, EnteringContext, SS))
+ ObjectType, EnteringContext, SS,
+ false, CorrectionFlagPtr)) {
+ // Identifier is not recognized as a nested name, but we can have
+ // mistyped '::' instead of ':'.
+ if (CorrectionFlagPtr && IsCorrectedToColon) {
+ ColonColon.setKind(tok::colon);
+ PP.EnterToken(Tok);
+ PP.EnterToken(ColonColon);
+ Tok = Identifier;
+ break;
+ }
SS.SetInvalid(SourceRange(IdLoc, CCLoc));
-
+ }
+ HasScopeSpecifier = true;
continue;
}
@@ -732,7 +767,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
!Intro.Captures.empty())) {
Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
/*AfterAmpersand=*/false);
- ConsumeCodeCompletionToken();
+ cutOffParsing();
break;
}
@@ -749,7 +784,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
else
Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
/*AfterAmpersand=*/false);
- ConsumeCodeCompletionToken();
+ cutOffParsing();
break;
}
@@ -758,7 +793,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
// Parse capture.
LambdaCaptureKind Kind = LCK_ByCopy;
SourceLocation Loc;
- IdentifierInfo* Id = 0;
+ IdentifierInfo *Id = nullptr;
SourceLocation EllipsisLoc;
ExprResult Init;
@@ -773,7 +808,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
/*AfterAmpersand=*/true);
- ConsumeCodeCompletionToken();
+ cutOffParsing();
break;
}
}
@@ -814,8 +849,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
// to save the necessary state, and restore it later.
EnterExpressionEvaluationContext EC(Actions,
Sema::PotentiallyEvaluated);
- if (Tok.is(tok::equal))
- ConsumeToken();
+ TryConsumeToken(tok::equal);
if (!SkippedInits)
Init = ParseInitializer();
@@ -830,8 +864,8 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
// [..., x = expr
//
// We need to find the end of the following expression in order to
- // determine whether this is an Obj-C message send's receiver, or a
- // lambda init-capture.
+ // determine whether this is an Obj-C message send's receiver, a
+ // C99 designator, or a lambda init-capture.
//
// Parse the expression to find where it ends, and annotate it back
// onto the tokens. We would have parsed this expression the same way
@@ -864,8 +898,8 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
ConsumeToken();
}
}
- } else if (Tok.is(tok::ellipsis))
- EllipsisLoc = ConsumeToken();
+ } else
+ TryConsumeToken(tok::ellipsis, EllipsisLoc);
}
// If this is an init capture, process the initialization expression
// right away. For lambda init-captures such as the following:
@@ -988,7 +1022,6 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
ParsedAttributes Attr(AttrFactory);
SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
SourceLocation EllipsisLoc;
-
if (Tok.isNot(tok::r_paren)) {
Actions.RecordParsingTemplateParameterDepth(TemplateParameterDepth);
@@ -1002,12 +1035,14 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
SourceLocation RParenLoc = T.getCloseLocation();
DeclEndLoc = RParenLoc;
+ // GNU-style attributes must be parsed before the mutable specifier to be
+ // compatible with GCC.
+ MaybeParseGNUAttributes(Attr, &DeclEndLoc);
+
// Parse 'mutable'[opt].
SourceLocation MutableLoc;
- if (Tok.is(tok::kw_mutable)) {
- MutableLoc = ConsumeToken();
+ if (TryConsumeToken(tok::kw_mutable, MutableLoc))
DeclEndLoc = MutableLoc;
- }
// Parse exception-specification[opt].
ExceptionSpecificationType ESpecType = EST_None;
@@ -1057,26 +1092,45 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
DynamicExceptionRanges.data(),
DynamicExceptions.size(),
NoexceptExpr.isUsable() ?
- NoexceptExpr.get() : 0,
+ NoexceptExpr.get() : nullptr,
LParenLoc, FunLocalRangeEnd, D,
TrailingReturnType),
Attr, DeclEndLoc);
- } else if (Tok.is(tok::kw_mutable) || Tok.is(tok::arrow)) {
- // It's common to forget that one needs '()' before 'mutable' or the
- // result type. Deal with this.
+ } else if (Tok.is(tok::kw_mutable) || Tok.is(tok::arrow) ||
+ Tok.is(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.
+ unsigned TokKind = 0;
+ switch (Tok.getKind()) {
+ case tok::kw_mutable: TokKind = 0; break;
+ case tok::arrow: TokKind = 1; break;
+ case tok::kw___attribute:
+ case tok::l_square: TokKind = 2; break;
+ default: llvm_unreachable("Unknown token kind");
+ }
+
Diag(Tok, diag::err_lambda_missing_parens)
- << Tok.is(tok::arrow)
+ << TokKind
<< FixItHint::CreateInsertion(Tok.getLocation(), "() ");
SourceLocation DeclLoc = Tok.getLocation();
SourceLocation DeclEndLoc = DeclLoc;
-
+
+ // GNU-style attributes must be parsed before the mutable specifier to be
+ // compatible with GCC.
+ ParsedAttributes Attr(AttrFactory);
+ MaybeParseGNUAttributes(Attr, &DeclEndLoc);
+
// Parse 'mutable', if it's there.
SourceLocation MutableLoc;
if (Tok.is(tok::kw_mutable)) {
MutableLoc = ConsumeToken();
DeclEndLoc = MutableLoc;
}
-
+
+ // Parse attribute-specifier[opt].
+ MaybeParseCXX11Attributes(Attr, &DeclEndLoc);
+
// Parse the return type, if there is one.
TypeResult TrailingReturnType;
if (Tok.is(tok::arrow)) {
@@ -1086,12 +1140,11 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
DeclEndLoc = Range.getEnd();
}
- ParsedAttributes Attr(AttrFactory);
SourceLocation NoLoc;
D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true,
/*isAmbiguous=*/false,
/*LParenLoc=*/NoLoc,
- /*Params=*/0,
+ /*Params=*/nullptr,
/*NumParams=*/0,
/*EllipsisLoc=*/NoLoc,
/*RParenLoc=*/NoLoc,
@@ -1103,10 +1156,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
MutableLoc,
EST_None,
/*ESpecLoc=*/NoLoc,
- /*Exceptions=*/0,
- /*ExceptionRanges=*/0,
+ /*Exceptions=*/nullptr,
+ /*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
- /*NoexceptExpr=*/0,
+ /*NoexceptExpr=*/nullptr,
DeclLoc, DeclEndLoc, D,
TrailingReturnType),
Attr, DeclEndLoc);
@@ -1131,7 +1184,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
BodyScope.Exit();
if (!Stmt.isInvalid())
- return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.take(), getCurScope());
+ return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.get(), getCurScope());
Actions.ActOnLambdaError(LambdaBeginLoc, getCurScope());
return ExprError();
@@ -1148,7 +1201,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
///
ExprResult Parser::ParseCXXCasts() {
tok::TokenKind Kind = Tok.getKind();
- const char *CastName = 0; // For error messages
+ const char *CastName = nullptr; // For error messages
switch (Kind) {
default: llvm_unreachable("Unknown C++ cast!");
@@ -1182,8 +1235,8 @@ ExprResult Parser::ParseCXXCasts() {
SourceLocation RAngleBracketLoc = Tok.getLocation();
- if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
- return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
+ if (ExpectAndConsume(tok::greater))
+ return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << tok::less);
SourceLocation LParenLoc, RParenLoc;
BalancedDelimiterTracker T(*this, tok::l_paren);
@@ -1200,7 +1253,7 @@ ExprResult Parser::ParseCXXCasts() {
Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
LAngleBracketLoc, DeclaratorInfo,
RAngleBracketLoc,
- T.getOpenLocation(), Result.take(),
+ T.getOpenLocation(), Result.get(),
T.getCloseLocation());
return Result;
@@ -1266,7 +1319,7 @@ ExprResult Parser::ParseCXXTypeid() {
return ExprError();
Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
- Result.release(), RParenLoc);
+ Result.get(), RParenLoc);
}
}
@@ -1314,7 +1367,7 @@ ExprResult Parser::ParseCXXUuidof() {
Result = Actions.ActOnCXXUuidof(OpLoc, T.getOpenLocation(),
/*isType=*/false,
- Result.release(), T.getCloseLocation());
+ Result.get(), T.getCloseLocation());
}
}
@@ -1364,7 +1417,7 @@ Parser::ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc,
assert(Tok.is(tok::coloncolon) &&"ParseOptionalCXXScopeSpecifier fail");
CCLoc = ConsumeToken();
} else {
- FirstTypeName.setIdentifier(0, SourceLocation());
+ FirstTypeName.setIdentifier(nullptr, SourceLocation());
}
// Parse the tilde.
@@ -1436,12 +1489,12 @@ ExprResult Parser::ParseThrowExpression() {
case tok::r_brace:
case tok::colon:
case tok::comma:
- return Actions.ActOnCXXThrow(getCurScope(), ThrowLoc, 0);
+ return Actions.ActOnCXXThrow(getCurScope(), ThrowLoc, nullptr);
default:
ExprResult Expr(ParseAssignmentExpression());
if (Expr.isInvalid()) return Expr;
- return Actions.ActOnCXXThrow(getCurScope(), ThrowLoc, Expr.take());
+ return Actions.ActOnCXXThrow(getCurScope(), ThrowLoc, Expr.get());
}
}
@@ -1481,7 +1534,7 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
ExprResult Init = ParseBraceInitializer();
if (Init.isInvalid())
return Init;
- Expr *InitList = Init.take();
+ Expr *InitList = Init.get();
return Actions.ActOnCXXTypeConstructExpr(TypeRep, SourceLocation(),
MultiExprArg(&InitList, 1),
SourceLocation());
@@ -1555,7 +1608,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut,
// Parse the expression.
ExprOut = ParseExpression(); // expression
- DeclOut = 0;
+ DeclOut = nullptr;
if (ExprOut.isInvalid())
return true;
@@ -1583,7 +1636,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut,
SkipUntil(tok::semi, StopAtSemi);
return true;
}
- DeclaratorInfo.setAsmLabel(AsmLabel.release());
+ DeclaratorInfo.setAsmLabel(AsmLabel.get());
DeclaratorInfo.SetRangeEnd(Loc);
}
@@ -1623,7 +1676,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut,
}
if (!InitExpr.isInvalid())
- Actions.AddInitializerToDecl(DeclOut, InitExpr.take(), !CopyInitialization,
+ Actions.AddInitializerToDecl(DeclOut, InitExpr.get(), !CopyInitialization,
DS.containsPlaceholderType());
else
Actions.ActOnInitializerError(DeclOut);
@@ -1667,6 +1720,8 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
const char *PrevSpec;
unsigned DiagID;
SourceLocation Loc = Tok.getLocation();
+ const clang::PrintingPolicy &Policy =
+ Actions.getASTContext().getPrintingPolicy();
switch (Tok.getKind()) {
case tok::identifier: // foo::bar
@@ -1679,7 +1734,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
case tok::annot_typename: {
if (getTypeAnnotation(Tok))
DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID,
- getTypeAnnotation(Tok));
+ getTypeAnnotation(Tok), Policy);
else
DS.SetTypeSpecError();
@@ -1693,19 +1748,19 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
if (Tok.is(tok::less) && getLangOpts().ObjC1)
ParseObjCProtocolQualifiers(DS);
- DS.Finish(Diags, PP);
+ DS.Finish(Diags, PP, Policy);
return;
}
// builtin types
case tok::kw_short:
- DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_long:
- DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw___int64:
- DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_signed:
DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID);
@@ -1714,47 +1769,47 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec, DiagID);
break;
case tok::kw_void:
- DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_char:
- DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_int:
- DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw___int128:
- DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_half:
- DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_float:
- DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_double:
- DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_wchar_t:
- DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_char16_t:
- DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_char32_t:
- DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_bool:
- DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID, Policy);
break;
case tok::annot_decltype:
case tok::kw_decltype:
DS.SetRangeEnd(ParseDecltypeSpecifier(DS));
- return DS.Finish(Diags, PP);
+ return DS.Finish(Diags, PP, Policy);
// GNU typeof support.
case tok::kw_typeof:
ParseTypeofSpecifier(DS);
- DS.Finish(Diags, PP);
+ DS.Finish(Diags, PP, Policy);
return;
}
if (Tok.is(tok::annot_typename))
@@ -1762,7 +1817,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
else
DS.SetRangeEnd(Tok.getLocation());
ConsumeToken();
- DS.Finish(Diags, PP);
+ DS.Finish(Diags, PP, Policy);
}
/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
@@ -1778,7 +1833,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
///
bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
ParseSpecifierQualifierList(DS, AS_none, DSC_type_specifier);
- DS.Finish(Diags, PP);
+ DS.Finish(Diags, PP, Actions.getASTContext().getPrintingPolicy());
return false;
}
@@ -1935,12 +1990,13 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
TemplateIdAnnotation *TemplateId
= TemplateIdAnnotation::Allocate(TemplateArgs.size(), TemplateIds);
+ // FIXME: Store name for literal operator too.
if (Id.getKind() == UnqualifiedId::IK_Identifier) {
TemplateId->Name = Id.Identifier;
TemplateId->Operator = OO_None;
TemplateId->TemplateNameLoc = Id.StartLocation;
} else {
- TemplateId->Name = 0;
+ TemplateId->Name = nullptr;
TemplateId->Operator = Id.OperatorFunctionId.Operator;
TemplateId->TemplateNameLoc = Id.StartLocation;
}
@@ -2139,13 +2195,13 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
TokLocs.push_back(ConsumeStringToken());
}
- StringLiteralParser Literal(Toks.data(), Toks.size(), PP);
+ StringLiteralParser Literal(Toks, PP);
if (Literal.hadError)
return true;
// Grab the literal operator's suffix, which will be either the next token
// or a ud-suffix from the string literal.
- IdentifierInfo *II = 0;
+ IdentifierInfo *II = nullptr;
SourceLocation SuffixLoc;
if (!Literal.getUDSuffix().empty()) {
II = &PP.getIdentifierTable().get(Literal.getUDSuffix());
@@ -2158,7 +2214,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
SuffixLoc = ConsumeToken();
TokLocs.push_back(SuffixLoc);
} else {
- Diag(Tok.getLocation(), diag::err_expected_ident);
+ Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
return true;
}
@@ -2183,9 +2239,10 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
}
Result.setLiteralOperatorId(II, KeywordLoc, SuffixLoc);
- return false;
+
+ return Actions.checkLiteralOperatorId(SS, Result);
}
-
+
// Parse a conversion-function-id.
//
// conversion-function-id: [C++ 12.3.2]
@@ -2205,8 +2262,8 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
// Parse the conversion-declarator, which is merely a sequence of
// ptr-operators.
Declarator D(DS, Declarator::ConversionIdContext);
- ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
-
+ ParseDeclaratorInternal(D, /*DirectDeclParser=*/nullptr);
+
// Finish up the type.
TypeResult Ty = Actions.ActOnTypeName(getCurScope(), D);
if (Ty.isInvalid())
@@ -2362,10 +2419,10 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
Result.getKind() == UnqualifiedId::IK_LiteralOperatorId) &&
(TemplateSpecified || Tok.is(tok::less)))
return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc,
- 0, SourceLocation(),
+ nullptr, SourceLocation(),
EnteringContext, ObjectType,
Result, TemplateSpecified);
-
+
return false;
}
@@ -2560,7 +2617,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
PlacementArgs, PlacementRParen,
- TypeIdParens, DeclaratorInfo, Initializer.take());
+ TypeIdParens, DeclaratorInfo, Initializer.get());
}
/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
@@ -2598,7 +2655,7 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) {
D.AddTypeInfo(DeclaratorChunk::getArray(0,
/*static=*/false, /*star=*/false,
- Size.release(),
+ Size.get(),
T.getOpenLocation(),
T.getCloseLocation()),
Attrs, T.getCloseLocation());
@@ -2675,82 +2732,20 @@ Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
if (Operand.isInvalid())
return Operand;
- return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, Operand.take());
-}
-
-static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
- switch(kind) {
- default: llvm_unreachable("Not a known unary type trait.");
- case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign;
- case tok::kw___has_nothrow_move_assign: return UTT_HasNothrowMoveAssign;
- case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
- case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy;
- case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign;
- case tok::kw___has_trivial_move_assign: return UTT_HasTrivialMoveAssign;
- case tok::kw___has_trivial_constructor:
- return UTT_HasTrivialDefaultConstructor;
- case tok::kw___has_trivial_move_constructor:
- return UTT_HasTrivialMoveConstructor;
- case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy;
- case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor;
- case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor;
- case tok::kw___is_abstract: return UTT_IsAbstract;
- case tok::kw___is_arithmetic: return UTT_IsArithmetic;
- case tok::kw___is_array: return UTT_IsArray;
- case tok::kw___is_class: return UTT_IsClass;
- case tok::kw___is_complete_type: return UTT_IsCompleteType;
- case tok::kw___is_compound: return UTT_IsCompound;
- case tok::kw___is_const: return UTT_IsConst;
- case tok::kw___is_empty: return UTT_IsEmpty;
- case tok::kw___is_enum: return UTT_IsEnum;
- case tok::kw___is_final: return UTT_IsFinal;
- case tok::kw___is_floating_point: return UTT_IsFloatingPoint;
- case tok::kw___is_function: return UTT_IsFunction;
- case tok::kw___is_fundamental: return UTT_IsFundamental;
- case tok::kw___is_integral: return UTT_IsIntegral;
- case tok::kw___is_interface_class: return UTT_IsInterfaceClass;
- case tok::kw___is_lvalue_reference: return UTT_IsLvalueReference;
- case tok::kw___is_member_function_pointer: return UTT_IsMemberFunctionPointer;
- case tok::kw___is_member_object_pointer: return UTT_IsMemberObjectPointer;
- case tok::kw___is_member_pointer: return UTT_IsMemberPointer;
- case tok::kw___is_object: return UTT_IsObject;
- case tok::kw___is_literal: return UTT_IsLiteral;
- case tok::kw___is_literal_type: return UTT_IsLiteral;
- case tok::kw___is_pod: return UTT_IsPOD;
- case tok::kw___is_pointer: return UTT_IsPointer;
- case tok::kw___is_polymorphic: return UTT_IsPolymorphic;
- case tok::kw___is_reference: return UTT_IsReference;
- case tok::kw___is_rvalue_reference: return UTT_IsRvalueReference;
- case tok::kw___is_scalar: return UTT_IsScalar;
- case tok::kw___is_sealed: return UTT_IsSealed;
- case tok::kw___is_signed: return UTT_IsSigned;
- case tok::kw___is_standard_layout: return UTT_IsStandardLayout;
- case tok::kw___is_trivial: return UTT_IsTrivial;
- case tok::kw___is_trivially_copyable: return UTT_IsTriviallyCopyable;
- case tok::kw___is_union: return UTT_IsUnion;
- case tok::kw___is_unsigned: return UTT_IsUnsigned;
- case tok::kw___is_void: return UTT_IsVoid;
- case tok::kw___is_volatile: return UTT_IsVolatile;
- }
-}
-
-static BinaryTypeTrait BinaryTypeTraitFromTokKind(tok::TokenKind kind) {
- switch(kind) {
- default: llvm_unreachable("Not a known binary type trait");
- case tok::kw___is_base_of: return BTT_IsBaseOf;
- case tok::kw___is_convertible: return BTT_IsConvertible;
- case tok::kw___is_same: return BTT_IsSame;
- case tok::kw___builtin_types_compatible_p: return BTT_TypeCompatible;
- case tok::kw___is_convertible_to: return BTT_IsConvertibleTo;
- case tok::kw___is_trivially_assignable: return BTT_IsTriviallyAssignable;
- }
+ return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, Operand.get());
}
static TypeTrait TypeTraitFromTokKind(tok::TokenKind kind) {
switch (kind) {
default: llvm_unreachable("Not a known type trait");
- case tok::kw___is_trivially_constructible:
- return TT_IsTriviallyConstructible;
+#define TYPE_TRAIT_1(Spelling, Name, Key) \
+case tok::kw_ ## Spelling: return UTT_ ## Name;
+#define TYPE_TRAIT_2(Spelling, Name, Key) \
+case tok::kw_ ## Spelling: return BTT_ ## Name;
+#include "clang/Basic/TokenKinds.def"
+#define TYPE_TRAIT_N(Spelling, Name, Key) \
+ case tok::kw_ ## Spelling: return TT_ ## Name;
+#include "clang/Basic/TokenKinds.def"
}
}
@@ -2770,87 +2765,33 @@ static ExpressionTrait ExpressionTraitFromTokKind(tok::TokenKind kind) {
}
}
-/// ParseUnaryTypeTrait - Parse the built-in unary type-trait
-/// pseudo-functions that allow implementation of the TR1/C++0x type traits
-/// templates.
-///
-/// primary-expression:
-/// [GNU] unary-type-trait '(' type-id ')'
-///
-ExprResult Parser::ParseUnaryTypeTrait() {
- UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind());
- SourceLocation Loc = ConsumeToken();
-
- BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen))
- return ExprError();
-
- // FIXME: Error reporting absolutely sucks! If the this fails to parse a type
- // there will be cryptic errors about mismatched parentheses and missing
- // specifiers.
- TypeResult Ty = ParseTypeName();
-
- T.consumeClose();
-
- if (Ty.isInvalid())
- return ExprError();
-
- return Actions.ActOnUnaryTypeTrait(UTT, Loc, Ty.get(), T.getCloseLocation());
-}
-
-/// ParseBinaryTypeTrait - Parse the built-in binary type-trait
-/// pseudo-functions that allow implementation of the TR1/C++0x type traits
-/// templates.
-///
-/// primary-expression:
-/// [GNU] binary-type-trait '(' type-id ',' type-id ')'
-///
-ExprResult Parser::ParseBinaryTypeTrait() {
- BinaryTypeTrait BTT = BinaryTypeTraitFromTokKind(Tok.getKind());
- SourceLocation Loc = ConsumeToken();
-
- BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen))
- return ExprError();
-
- TypeResult LhsTy = ParseTypeName();
- if (LhsTy.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
-
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma)) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
-
- TypeResult RhsTy = ParseTypeName();
- if (RhsTy.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
+static unsigned TypeTraitArity(tok::TokenKind kind) {
+ switch (kind) {
+ default: llvm_unreachable("Not a known type trait");
+#define TYPE_TRAIT(N,Spelling,K) case tok::kw_##Spelling: return N;
+#include "clang/Basic/TokenKinds.def"
}
-
- T.consumeClose();
-
- return Actions.ActOnBinaryTypeTrait(BTT, Loc, LhsTy.get(), RhsTy.get(),
- T.getCloseLocation());
}
/// \brief Parse the built-in type-trait pseudo-functions that allow
/// implementation of the TR1/C++11 type traits templates.
///
/// primary-expression:
+/// unary-type-trait '(' type-id ')'
+/// binary-type-trait '(' type-id ',' type-id ')'
/// type-trait '(' type-id-seq ')'
///
/// type-id-seq:
/// type-id ...[opt] type-id-seq[opt]
///
ExprResult Parser::ParseTypeTrait() {
- TypeTrait Kind = TypeTraitFromTokKind(Tok.getKind());
+ tok::TokenKind Kind = Tok.getKind();
+ unsigned Arity = TypeTraitArity(Kind);
+
SourceLocation Loc = ConsumeToken();
BalancedDelimiterTracker Parens(*this, tok::l_paren);
- if (Parens.expectAndConsume(diag::err_expected_lparen))
+ if (Parens.expectAndConsume())
return ExprError();
SmallVector<ParsedType, 2> Args;
@@ -2873,19 +2814,26 @@ ExprResult Parser::ParseTypeTrait() {
// Add this type to the list of arguments.
Args.push_back(Ty.get());
-
- if (Tok.is(tok::comma)) {
- ConsumeToken();
- continue;
- }
-
- break;
- } while (true);
-
+ } while (TryConsumeToken(tok::comma));
+
if (Parens.consumeClose())
return ExprError();
-
- return Actions.ActOnTypeTrait(Kind, Loc, Args, Parens.getCloseLocation());
+
+ SourceLocation EndLoc = Parens.getCloseLocation();
+
+ if (Arity && Args.size() != Arity) {
+ Diag(EndLoc, diag::err_type_trait_arity)
+ << Arity << 0 << (Arity > 1) << (int)Args.size() << SourceRange(Loc);
+ return ExprError();
+ }
+
+ if (!Arity && Args.empty()) {
+ Diag(EndLoc, diag::err_type_trait_arity)
+ << 1 << 1 << 1 << (int)Args.size() << SourceRange(Loc);
+ return ExprError();
+ }
+
+ return Actions.ActOnTypeTrait(TypeTraitFromTokKind(Kind), Loc, Args, EndLoc);
}
/// ParseArrayTypeTrait - Parse the built-in array type-trait
@@ -2900,7 +2848,7 @@ ExprResult Parser::ParseArrayTypeTrait() {
SourceLocation Loc = ConsumeToken();
BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen))
+ if (T.expectAndConsume())
return ExprError();
TypeResult Ty = ParseTypeName();
@@ -2913,11 +2861,11 @@ ExprResult Parser::ParseArrayTypeTrait() {
switch (ATT) {
case ATT_ArrayRank: {
T.consumeClose();
- return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), NULL,
+ return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), nullptr,
T.getCloseLocation());
}
case ATT_ArrayExtent: {
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma)) {
+ if (ExpectAndConsume(tok::comma)) {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
@@ -2943,7 +2891,7 @@ ExprResult Parser::ParseExpressionTrait() {
SourceLocation Loc = ConsumeToken();
BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen))
+ if (T.expectAndConsume())
return ExprError();
ExprResult Expr = ParseExpression();
@@ -2961,7 +2909,8 @@ ExprResult Parser::ParseExpressionTrait() {
ExprResult
Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
ParsedType &CastTy,
- BalancedDelimiterTracker &Tracker) {
+ BalancedDelimiterTracker &Tracker,
+ ColonProtectionRAIIObject &ColonProt) {
assert(getLangOpts().CPlusPlus && "Should only be called for C++!");
assert(ExprType == CastExpr && "Compound literals are not ambiguous!");
assert(isTypeIdInParens() && "Not a type-id!");
@@ -3003,13 +2952,13 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
ParseAs = CompoundLiteral;
} else {
bool NotCastExpr;
- // FIXME: Special-case ++ and --: "(S())++;" is not a cast-expression
if (Tok.is(tok::l_paren) && NextToken().is(tok::r_paren)) {
NotCastExpr = true;
} else {
// Try parsing the cast-expression that may follow.
// If it is not a cast-expression, NotCastExpr will be true and no token
// will be consumed.
+ ColonProt.restore();
Result = ParseCastExpression(false/*isUnaryExpression*/,
false/*isAddressofOperand*/,
NotCastExpr,
@@ -3035,17 +2984,24 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
if (ParseAs >= CompoundLiteral) {
// Parse the type declarator.
DeclSpec DS(AttrFactory);
- ParseSpecifierQualifierList(DS);
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
- ParseDeclarator(DeclaratorInfo);
+ {
+ ColonProtectionRAIIObject InnerColonProtection(*this);
+ ParseSpecifierQualifierList(DS);
+ ParseDeclarator(DeclaratorInfo);
+ }
// Match the ')'.
Tracker.consumeClose();
+ ColonProt.restore();
if (ParseAs == CompoundLiteral) {
ExprType = CompoundLiteral;
- TypeResult Ty = ParseTypeName();
- return ParseCompoundLiteralExpression(Ty.get(),
+ if (DeclaratorInfo.isInvalidType())
+ return ExprError();
+
+ TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
+ return ParseCompoundLiteralExpression(Ty.get(),
Tracker.getOpenLocation(),
Tracker.getCloseLocation());
}
@@ -3060,7 +3016,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
if (!Result.isInvalid())
Result = Actions.ActOnCastExpr(getCurScope(), Tracker.getOpenLocation(),
DeclaratorInfo, CastTy,
- Tracker.getCloseLocation(), Result.take());
+ Tracker.getCloseLocation(), Result.get());
return Result;
}
@@ -3071,7 +3027,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
Result = ParseExpression();
if (!Result.isInvalid() && Tok.is(tok::r_paren))
Result = Actions.ActOnParenExpr(Tracker.getOpenLocation(),
- Tok.getLocation(), Result.take());
+ Tok.getLocation(), Result.get());
// Match the ')'.
if (Result.isInvalid()) {
diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp
index 37f74bbcd51b..8536420088f3 100644
--- a/lib/Parse/ParseInit.cpp
+++ b/lib/Parse/ParseInit.cpp
@@ -66,47 +66,29 @@ bool Parser::MayBeDesignationStart() {
}
// Parse up to (at most) the token after the closing ']' to determine
- // whether this is a C99 designator or a lambda.
+ // whether this is a C99 designator or a lambda.
TentativeParsingAction Tentative(*this);
- ConsumeBracket();
- while (true) {
- switch (Tok.getKind()) {
- case tok::equal:
- case tok::amp:
- case tok::identifier:
- case tok::kw_this:
- // These tokens can occur in a capture list or a constant-expression.
- // Keep looking.
- ConsumeToken();
- continue;
-
- case tok::comma:
- // Since a comma cannot occur in a constant-expression, this must
- // be a lambda.
- Tentative.Revert();
- return false;
-
- case tok::r_square: {
- // Once we hit the closing square bracket, we look at the next
- // token. If it's an '=', this is a designator. Otherwise, it's a
- // lambda expression. This decision favors lambdas over the older
- // GNU designator syntax, which allows one to omit the '=', but is
- // consistent with GCC.
- ConsumeBracket();
- tok::TokenKind Kind = Tok.getKind();
- Tentative.Revert();
- return Kind == tok::equal;
- }
-
- default:
- // Anything else cannot occur in a lambda capture list, so it
- // must be a designator.
- Tentative.Revert();
- return true;
- }
+
+ LambdaIntroducer Intro;
+ bool SkippedInits = false;
+ Optional<unsigned> DiagID(ParseLambdaIntroducer(Intro, &SkippedInits));
+
+ if (DiagID) {
+ // If this can't be a lambda capture list, it's a designator.
+ Tentative.Revert();
+ return true;
}
-
- return true;
+
+ // Once we hit the closing square bracket, we look at the next
+ // token. If it's an '=', this is a designator. Otherwise, it's a
+ // lambda expression. This decision favors lambdas over the older
+ // GNU designator syntax, which allows one to omit the '=', but is
+ // consistent with GCC.
+ tok::TokenKind Kind = Tok.getKind();
+ // FIXME: If we didn't skip any inits, parse the lambda from here
+ // rather than throwing away then reparsing the LambdaIntroducer.
+ Tentative.Revert();
+ return Kind == tok::equal;
}
static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc,
@@ -237,7 +219,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
ConsumeToken(),
ParsedType(),
- 0);
+ nullptr);
}
// Parse the receiver, which is either a type or an expression.
@@ -255,7 +237,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
SourceLocation(),
ParsedType::getFromOpaquePtr(TypeOrExpr),
- 0);
+ nullptr);
}
// If the receiver was an expression, we still don't know
@@ -282,7 +264,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
ConsumeToken(),
ParsedType(),
- 0);
+ nullptr);
ConsumeToken(); // the identifier
if (!ReceiverType) {
SkipUntil(tok::r_square, StopAtSemi);
@@ -292,7 +274,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
SourceLocation(),
ReceiverType,
- 0);
+ nullptr);
case Sema::ObjCInstanceMessage:
// Fall through; we'll just parse the expression and
@@ -327,12 +309,12 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
SourceLocation(),
ParsedType(),
- Idx.take());
+ Idx.get());
}
// If this is a normal array designator, remember it.
if (Tok.isNot(tok::ellipsis)) {
- Desig.AddDesignator(Designator::getArray(Idx.release(), StartLoc));
+ Desig.AddDesignator(Designator::getArray(Idx.get(), StartLoc));
} else {
// Handle the gnu array range extension.
Diag(Tok, diag::ext_gnu_array_range);
@@ -343,8 +325,8 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
SkipUntil(tok::r_square, StopAtSemi);
return RHS;
}
- Desig.AddDesignator(Designator::getArrayRange(Idx.release(),
- RHS.release(),
+ Desig.AddDesignator(Designator::getArrayRange(Idx.get(),
+ RHS.get(),
StartLoc, EllipsisLoc));
}
@@ -444,7 +426,7 @@ ExprResult Parser::ParseBraceInitializer() {
// If we couldn't parse the subelement, bail out.
if (!SubElt.isInvalid()) {
- InitExprs.push_back(SubElt.release());
+ InitExprs.push_back(SubElt.get());
} else {
InitExprsOk = false;
@@ -493,7 +475,7 @@ bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
BalancedDelimiterTracker Braces(*this, tok::l_brace);
if (Braces.consumeOpen()) {
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
return false;
}
@@ -512,7 +494,7 @@ bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
return false;
}
- while (Tok.isNot(tok::eof)) {
+ while (!isEofOrEom()) {
trailingComma = false;
// If we know that this cannot be a designation, just parse the nested
// initializer directly.
@@ -527,7 +509,7 @@ bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
// If we couldn't parse the subelement, bail out.
if (!SubElt.isInvalid())
- InitExprs.push_back(SubElt.release());
+ InitExprs.push_back(SubElt.get());
else
InitExprsOk = false;
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 86f38cfee37a..7fe72ec0c3b1 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -51,8 +51,8 @@ Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() {
cutOffParsing();
return DeclGroupPtrTy();
}
-
- Decl *SingleDecl = 0;
+
+ Decl *SingleDecl = nullptr;
switch (Tok.getObjCKeywordID()) {
case tok::objc_class:
return ParseObjCAtClassDeclaration(AtLoc);
@@ -81,13 +81,13 @@ Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() {
case tok::objc_import:
if (getLangOpts().Modules)
return ParseModuleImport(AtLoc);
-
- // Fall through
-
+ Diag(AtLoc, diag::err_atimport);
+ SkipUntil(tok::semi);
+ return Actions.ConvertDeclToDeclGroup(nullptr);
default:
Diag(AtLoc, diag::err_unexpected_at);
SkipUntil(tok::semi);
- SingleDecl = 0;
+ SingleDecl = nullptr;
break;
}
return Actions.ConvertDeclToDeclGroup(SingleDecl);
@@ -107,23 +107,21 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
while (1) {
MaybeSkipAttributes(tok::objc_class);
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::semi);
- return Actions.ConvertDeclToDeclGroup(0);
+ return Actions.ConvertDeclToDeclGroup(nullptr);
}
ClassNames.push_back(Tok.getIdentifierInfo());
ClassLocs.push_back(Tok.getLocation());
ConsumeToken();
- if (Tok.isNot(tok::comma))
+ if (!TryConsumeToken(tok::comma))
break;
-
- ConsumeToken();
}
// Consume the ';'.
- if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
- return Actions.ConvertDeclToDeclGroup(0);
+ if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@class"))
+ return Actions.ConvertDeclToDeclGroup(nullptr);
return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(),
ClassLocs.data(),
@@ -189,14 +187,15 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCInterfaceDecl(getCurScope());
cutOffParsing();
- return 0;
+ return nullptr;
}
MaybeSkipAttributes(tok::objc_interface);
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident); // missing class or category name.
- return 0;
+ Diag(Tok, diag::err_expected)
+ << tok::identifier; // missing class or category name.
+ return nullptr;
}
// We have a class or category name - consume it.
@@ -209,11 +208,11 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
T.consumeOpen();
SourceLocation categoryLoc;
- IdentifierInfo *categoryId = 0;
+ IdentifierInfo *categoryId = nullptr;
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCInterfaceCategory(getCurScope(), nameId, nameLoc);
cutOffParsing();
- return 0;
+ return nullptr;
}
// For ObjC2, the category name is optional (not an error).
@@ -222,14 +221,15 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
categoryLoc = ConsumeToken();
}
else if (!getLangOpts().ObjC2) {
- Diag(Tok, diag::err_expected_ident); // missing category name.
- return 0;
+ Diag(Tok, diag::err_expected)
+ << tok::identifier; // missing category name.
+ return nullptr;
}
T.consumeClose();
if (T.getCloseLocation().isInvalid())
- return 0;
-
+ return nullptr;
+
if (!attrs.empty()) { // categories don't support attributes.
Diag(nameLoc, diag::err_objc_no_attributes_on_category);
attrs.clear();
@@ -242,7 +242,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
if (Tok.is(tok::less) &&
ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
LAngleLoc, EndProtoLoc))
- return 0;
+ return nullptr;
Decl *CategoryType =
Actions.ActOnStartCategoryInterface(AtLoc,
@@ -260,7 +260,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
return CategoryType;
}
// Parse a class interface.
- IdentifierInfo *superClassId = 0;
+ IdentifierInfo *superClassId = nullptr;
SourceLocation superClassLoc;
if (Tok.is(tok::colon)) { // a super class is specified.
@@ -270,12 +270,13 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCSuperclass(getCurScope(), nameId, nameLoc);
cutOffParsing();
- return 0;
+ return nullptr;
}
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident); // missing super class name.
- return 0;
+ Diag(Tok, diag::err_expected)
+ << tok::identifier; // missing super class name.
+ return nullptr;
}
superClassId = Tok.getIdentifierInfo();
superClassLoc = ConsumeToken();
@@ -287,7 +288,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
if (Tok.is(tok::less) &&
ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
LAngleLoc, EndProtoLoc))
- return 0;
+ return nullptr;
if (Tok.isNot(tok::less))
Actions.ActOnTypedefedProtocols(ProtocolRefs, superClassId, superClassLoc);
@@ -328,8 +329,8 @@ public:
MethodImplKind(MethodImplKind) {
}
- void invoke(ParsingFieldDeclarator &FD) {
- if (FD.D.getIdentifier() == 0) {
+ void invoke(ParsingFieldDeclarator &FD) override {
+ if (FD.D.getIdentifier() == nullptr) {
P.Diag(AtLoc, diag::err_objc_property_requires_field_name)
<< FD.D.getSourceRange();
return;
@@ -423,7 +424,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
}
// If we got to the end of the file, exit the loop.
- if (Tok.is(tok::eof))
+ if (isEofOrEom())
break;
// Code completion within an Objective-C interface.
@@ -576,7 +577,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
const IdentifierInfo *II = Tok.getIdentifierInfo();
// If this is not an identifier at all, bail out early.
- if (II == 0) {
+ if (!II) {
T.consumeClose();
return;
}
@@ -610,8 +611,10 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
unsigned DiagID = IsSetter ? diag::err_objc_expected_equal_for_setter :
diag::err_objc_expected_equal_for_getter;
- if (ExpectAndConsume(tok::equal, DiagID, "", tok::r_paren))
+ if (ExpectAndConsume(tok::equal, DiagID)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return;
+ }
if (Tok.is(tok::code_completion)) {
if (IsSetter)
@@ -636,10 +639,11 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter);
DS.setSetterName(SelIdent);
- if (ExpectAndConsume(tok::colon,
- diag::err_expected_colon_after_setter_name, "",
- tok::r_paren))
+ if (ExpectAndConsume(tok::colon,
+ diag::err_expected_colon_after_setter_name)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return;
+ }
} else {
DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter);
DS.setGetterName(SelIdent);
@@ -694,7 +698,7 @@ IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) {
switch (Tok.getKind()) {
default:
- return 0;
+ return nullptr;
case tok::ampamp:
case tok::ampequal:
case tok::amp:
@@ -713,7 +717,7 @@ IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) {
SelectorLoc = ConsumeToken();
return II;
}
- return 0;
+ return nullptr;
}
case tok::identifier:
@@ -841,7 +845,7 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
}
DS.setObjCDeclQualifier(Qual);
ConsumeToken();
- II = 0;
+ II = nullptr;
break;
}
@@ -862,7 +866,7 @@ static void takeDeclAttributes(ParsedAttributes &attrs,
// Clear out the next pointer. We're really completely
// destroying the internal invariants of the declarator here,
// but it doesn't matter because we're done with it.
- cur->setNext(0);
+ cur->setNext(nullptr);
attrs.add(cur);
}
}
@@ -893,7 +897,8 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
ParsedAttributes *paramAttrs) {
assert(context == Declarator::ObjCParameterContext ||
context == Declarator::ObjCResultContext);
- assert((paramAttrs != 0) == (context == Declarator::ObjCParameterContext));
+ assert((paramAttrs != nullptr) ==
+ (context == Declarator::ObjCParameterContext));
assert(Tok.is(tok::l_paren) && "expected (");
@@ -990,14 +995,15 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
/*ReturnType=*/ ParsedType());
cutOffParsing();
- return 0;
+ return nullptr;
}
// Parse the return type if present.
ParsedType ReturnType;
ObjCDeclSpec DSRet;
if (Tok.is(tok::l_paren))
- ReturnType = ParseObjCTypeName(DSRet, Declarator::ObjCResultContext, 0);
+ ReturnType = ParseObjCTypeName(DSRet, Declarator::ObjCResultContext,
+ nullptr);
// If attributes exist before the method, parse them.
ParsedAttributes methodAttrs(AttrFactory);
@@ -1008,7 +1014,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
ReturnType);
cutOffParsing();
- return 0;
+ return nullptr;
}
// Now parse the selector.
@@ -1021,7 +1027,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
<< SourceRange(mLoc, Tok.getLocation());
// Skip until we get a ; or @.
SkipUntil(tok::at, StopAtSemi | StopBeforeMatch);
- return 0;
+ return nullptr;
}
SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo;
@@ -1034,7 +1040,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
Decl *Result
= Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(),
mType, DSRet, ReturnType,
- selLoc, Sel, 0,
+ selLoc, Sel, nullptr,
CParamInfo.data(), CParamInfo.size(),
methodAttrs.getList(), MethodImplKind,
false, MethodDefinition);
@@ -1054,11 +1060,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
Sema::ObjCArgInfo ArgInfo;
// Each iteration parses a single keyword argument.
- if (Tok.isNot(tok::colon)) {
- Diag(Tok, diag::err_expected_colon);
+ if (ExpectAndConsume(tok::colon))
break;
- }
- ConsumeToken(); // Eat the ':'.
ArgInfo.Type = ParsedType();
if (Tok.is(tok::l_paren)) // Parse the argument type if present.
@@ -1068,7 +1071,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
// If attributes exist before the argument name, parse them.
// Regardless, collect all the attributes we've parsed so far.
- ArgInfo.ArgAttrs = 0;
+ ArgInfo.ArgAttrs = nullptr;
if (getLangOpts().ObjC2) {
MaybeParseGNUAttributes(paramAttrs);
ArgInfo.ArgAttrs = paramAttrs.getList();
@@ -1082,11 +1085,12 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
/*AtParameterName=*/true,
ReturnType, KeyIdents);
cutOffParsing();
- return 0;
+ return nullptr;
}
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident); // missing argument name.
+ Diag(Tok, diag::err_expected)
+ << tok::identifier; // missing argument name.
break;
}
@@ -1108,7 +1112,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
/*AtParameterName=*/false,
ReturnType, KeyIdents);
cutOffParsing();
- return 0;
+ return nullptr;
}
// Check for another keyword selector.
@@ -1150,7 +1154,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
CParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
ParmDecl.getIdentifierLoc(),
Param,
- 0));
+ nullptr));
}
// FIXME: Add support for optional parameter list...
@@ -1159,8 +1163,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
MaybeParseGNUAttributes(methodAttrs);
if (KeyIdents.size() == 0)
- return 0;
-
+ return nullptr;
+
Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),
&KeyIdents[0]);
Decl *Result
@@ -1198,7 +1202,7 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,
}
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::greater, StopAtSemi);
return true;
}
@@ -1207,9 +1211,8 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,
ProtocolLocs.push_back(Tok.getLocation());
ConsumeToken();
- if (Tok.isNot(tok::comma))
+ if (!TryConsumeToken(tok::comma))
break;
- ConsumeToken();
}
// Consume the '>'.
@@ -1254,7 +1257,7 @@ void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocatio
// for code rewriting tools that need to be aware of the empty list.
Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl,
AllIvarDecls,
- T.getOpenLocation(), T.getCloseLocation(), 0);
+ T.getOpenLocation(), T.getCloseLocation(), nullptr);
}
/// objc-class-instance-variables:
@@ -1289,7 +1292,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
BalancedDelimiterTracker T(*this, tok::l_brace);
T.consumeOpen();
// While we still have something to read, read the instance variables.
- while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
// Each iteration of this loop reads one objc-instance-variable-decl.
// Check for extraneous top-level semicolon.
@@ -1299,9 +1302,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
}
// Set the default visibility to private.
- if (Tok.is(tok::at)) { // parse objc-visibility-spec
- ConsumeToken(); // eat the @ sign
-
+ if (TryConsumeToken(tok::at)) { // parse objc-visibility-spec
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCAtVisibility(getCurScope());
return cutOffParsing();
@@ -1349,7 +1350,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
P(P), IDecl(IDecl), visibility(V), AllIvarDecls(AllIvarDecls) {
}
- void invoke(ParsingFieldDeclarator &FD) {
+ void invoke(ParsingFieldDeclarator &FD) override {
P.Actions.ActOnObjCContainerStartDefinition(IDecl);
// Install the declarator into the interface decl.
Decl *Field
@@ -1412,16 +1413,15 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
MaybeSkipAttributes(tok::objc_protocol);
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident); // missing protocol name.
+ Diag(Tok, diag::err_expected) << tok::identifier; // missing protocol name.
return DeclGroupPtrTy();
}
// Save the protocol name, then consume it.
IdentifierInfo *protocolName = Tok.getIdentifierInfo();
SourceLocation nameLoc = ConsumeToken();
- if (Tok.is(tok::semi)) { // forward declaration of one protocol.
+ if (TryConsumeToken(tok::semi)) { // forward declaration of one protocol.
IdentifierLocPair ProtoInfo(protocolName, nameLoc);
- ConsumeToken();
return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1,
attrs.getList());
}
@@ -1436,7 +1436,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
while (1) {
ConsumeToken(); // the ','
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::semi);
return DeclGroupPtrTy();
}
@@ -1448,7 +1448,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
break;
}
// Consume the ';'.
- if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol"))
+ if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@protocol"))
return DeclGroupPtrTy();
return Actions.ActOnForwardProtocolDeclaration(AtLoc,
@@ -1505,19 +1505,20 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
MaybeSkipAttributes(tok::objc_implementation);
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident); // missing class or category name.
+ Diag(Tok, diag::err_expected)
+ << tok::identifier; // missing class or category name.
return DeclGroupPtrTy();
}
// We have a class or category name - consume it.
IdentifierInfo *nameId = Tok.getIdentifierInfo();
SourceLocation nameLoc = ConsumeToken(); // consume class or category name
- Decl *ObjCImpDecl = 0;
+ Decl *ObjCImpDecl = nullptr;
if (Tok.is(tok::l_paren)) {
// we have a category implementation.
ConsumeParen();
SourceLocation categoryLoc, rparenLoc;
- IdentifierInfo *categoryId = 0;
+ IdentifierInfo *categoryId = nullptr;
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCImplementationCategory(getCurScope(), nameId, nameLoc);
@@ -1529,11 +1530,12 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
categoryId = Tok.getIdentifierInfo();
categoryLoc = ConsumeToken();
} else {
- Diag(Tok, diag::err_expected_ident); // missing category name.
+ Diag(Tok, diag::err_expected)
+ << tok::identifier; // missing category name.
return DeclGroupPtrTy();
}
if (Tok.isNot(tok::r_paren)) {
- Diag(Tok, diag::err_expected_rparen);
+ Diag(Tok, diag::err_expected) << tok::r_paren;
SkipUntil(tok::r_paren); // don't stop at ';'
return DeclGroupPtrTy();
}
@@ -1551,12 +1553,12 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
} else {
// We have a class implementation
SourceLocation superClassLoc;
- IdentifierInfo *superClassId = 0;
- if (Tok.is(tok::colon)) {
+ IdentifierInfo *superClassId = nullptr;
+ if (TryConsumeToken(tok::colon)) {
// We have a super class
- ConsumeToken();
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident); // missing super class name.
+ Diag(Tok, diag::err_expected)
+ << tok::identifier; // missing super class name.
return DeclGroupPtrTy();
}
superClassId = Tok.getIdentifierInfo();
@@ -1582,7 +1584,7 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
{
ObjCImplParsingDataRAII ObjCImplParsing(*this, ObjCImpDecl);
- while (!ObjCImplParsing.isFinished() && Tok.isNot(tok::eof)) {
+ while (!ObjCImplParsing.isFinished() && !isEofOrEom()) {
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
MaybeParseMicrosoftAttributes(attrs);
@@ -1612,14 +1614,14 @@ Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() {
if (!Finished) {
finish(P.Tok.getLocation());
- if (P.Tok.is(tok::eof)) {
+ if (P.isEofOrEom()) {
P.Diag(P.Tok, diag::err_objc_missing_end)
<< FixItHint::CreateInsertion(P.Tok.getLocation(), "\n@end\n");
P.Diag(Dcl->getLocStart(), diag::note_objc_container_start)
<< Sema::OCK_Implementation;
}
}
- P.CurParsedObjCImpl = 0;
+ P.CurParsedObjCImpl = nullptr;
assert(LateParsedObjCMethods.empty());
}
@@ -1655,19 +1657,18 @@ Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
"ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");
ConsumeToken(); // consume compatibility_alias
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
- return 0;
+ Diag(Tok, diag::err_expected) << tok::identifier;
+ return nullptr;
}
IdentifierInfo *aliasId = Tok.getIdentifierInfo();
SourceLocation aliasLoc = ConsumeToken(); // consume alias-name
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
- return 0;
+ Diag(Tok, diag::err_expected) << tok::identifier;
+ return nullptr;
}
IdentifierInfo *classId = Tok.getIdentifierInfo();
SourceLocation classLoc = ConsumeToken(); // consume class-name;
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
- "@compatibility_alias");
+ ExpectAndConsume(tok::semi, diag::err_expected_after, "@compatibility_alias");
return Actions.ActOnCompatibilityAlias(atLoc, aliasId, aliasLoc,
classId, classLoc);
}
@@ -1692,31 +1693,29 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPropertyDefinition(getCurScope());
cutOffParsing();
- return 0;
+ return nullptr;
}
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_synthesized_property_name);
SkipUntil(tok::semi);
- return 0;
+ return nullptr;
}
-
- IdentifierInfo *propertyIvar = 0;
+
+ IdentifierInfo *propertyIvar = nullptr;
IdentifierInfo *propertyId = Tok.getIdentifierInfo();
SourceLocation propertyLoc = ConsumeToken(); // consume property name
SourceLocation propertyIvarLoc;
- if (Tok.is(tok::equal)) {
+ if (TryConsumeToken(tok::equal)) {
// property '=' ivar-name
- ConsumeToken(); // consume '='
-
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId);
cutOffParsing();
- return 0;
+ return nullptr;
}
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
break;
}
propertyIvar = Tok.getIdentifierInfo();
@@ -1728,8 +1727,8 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
break;
ConsumeToken(); // consume ','
}
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@synthesize");
- return 0;
+ ExpectAndConsume(tok::semi, diag::err_expected_after, "@synthesize");
+ return nullptr;
}
/// property-dynamic:
@@ -1747,26 +1746,26 @@ Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPropertyDefinition(getCurScope());
cutOffParsing();
- return 0;
+ return nullptr;
}
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::semi);
- return 0;
+ return nullptr;
}
IdentifierInfo *propertyId = Tok.getIdentifierInfo();
SourceLocation propertyLoc = ConsumeToken(); // consume property name
Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, false,
- propertyId, 0, SourceLocation());
+ propertyId, nullptr, SourceLocation());
if (Tok.isNot(tok::comma))
break;
ConsumeToken(); // consume ','
}
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@dynamic");
- return 0;
+ ExpectAndConsume(tok::semi, diag::err_expected_after, "@dynamic");
+ return nullptr;
}
/// objc-throw-statement:
@@ -1783,8 +1782,8 @@ StmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) {
}
}
// consume ';'
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@throw");
- return Actions.ActOnObjCAtThrowStmt(atLoc, Res.take(), getCurScope());
+ ExpectAndConsume(tok::semi, diag::err_expected_after, "@throw");
+ return Actions.ActOnObjCAtThrowStmt(atLoc, Res.get(), getCurScope());
}
/// objc-synchronized-statement:
@@ -1806,7 +1805,7 @@ Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
ConsumeParen(); // ')'
} else {
if (!operand.isInvalid())
- Diag(Tok, diag::err_expected_rparen);
+ Diag(Tok, diag::err_expected) << tok::r_paren;
// Skip forward until we see a left brace, but don't consume it.
SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);
@@ -1815,13 +1814,13 @@ Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
// Require a compound statement.
if (Tok.isNot(tok::l_brace)) {
if (!operand.isInvalid())
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
return StmtError();
}
// Check the @synchronized operand now.
if (!operand.isInvalid())
- operand = Actions.ActOnObjCAtSynchronizedOperand(atLoc, operand.take());
+ operand = Actions.ActOnObjCAtSynchronizedOperand(atLoc, operand.get());
// Parse the compound statement within a new scope.
ParseScope bodyScope(this, Scope::DeclScope);
@@ -1855,7 +1854,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
ConsumeToken(); // consume try
if (Tok.isNot(tok::l_brace)) {
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
return StmtError();
}
StmtVector CatchStmts;
@@ -1877,7 +1876,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
SourceLocation AtCatchFinallyLoc = ConsumeToken();
if (Tok.isObjCAtKeyword(tok::objc_catch)) {
- Decl *FirstPart = 0;
+ Decl *FirstPart = nullptr;
ConsumeToken(); // consume catch
if (Tok.is(tok::l_paren)) {
ConsumeParen();
@@ -1905,16 +1904,16 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
if (Tok.is(tok::l_brace))
CatchBody = ParseCompoundStatementBody();
else
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
if (CatchBody.isInvalid())
CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
StmtResult Catch = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc,
RParenLoc,
FirstPart,
- CatchBody.take());
+ CatchBody.get());
if (!Catch.isInvalid())
- CatchStmts.push_back(Catch.release());
+ CatchStmts.push_back(Catch.get());
} else {
Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)
@@ -1931,11 +1930,11 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
if (Tok.is(tok::l_brace))
FinallyBody = ParseCompoundStatementBody();
else
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
if (FinallyBody.isInvalid())
FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
- FinallyBody.take());
+ FinallyBody.get());
catch_or_finally_seen = true;
break;
}
@@ -1945,9 +1944,9 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
return StmtError();
}
- return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.take(),
+ return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.get(),
CatchStmts,
- FinallyStmt.take());
+ FinallyStmt.get());
}
/// objc-autoreleasepool-statement:
@@ -1957,7 +1956,7 @@ StmtResult
Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) {
ConsumeToken(); // consume autoreleasepool
if (Tok.isNot(tok::l_brace)) {
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
return StmtError();
}
// Enter a scope to hold everything within the compound stmt. Compound
@@ -1970,7 +1969,7 @@ Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) {
if (AutoreleasePoolBody.isInvalid())
AutoreleasePoolBody = Actions.ActOnNullStmt(Tok.getLocation());
return Actions.ActOnObjCAutoreleasePoolStmt(atLoc,
- AutoreleasePoolBody.take());
+ AutoreleasePoolBody.get());
}
/// StashAwayMethodOrFunctionBodyTokens - Consume the tokens and store them
@@ -2036,13 +2035,13 @@ Decl *Parser::ParseObjCMethodDefinition() {
// If we didn't find the '{', bail out.
if (Tok.isNot(tok::l_brace))
- return 0;
+ return nullptr;
}
if (!MDecl) {
ConsumeBrace();
SkipUntil(tok::r_brace);
- return 0;
+ return nullptr;
}
// Allow the rest of sema to find private method decl implementations.
@@ -2100,7 +2099,7 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
SourceLocation OpLoc = ConsumeToken();
if (!Tok.is(tok::numeric_constant)) {
- const char *Symbol = 0;
+ const char *Symbol = nullptr;
switch (Kind) {
case tok::minus: Symbol = "-"; break;
case tok::plus: Symbol = "+"; break;
@@ -2117,12 +2116,12 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
}
ConsumeToken(); // Consume the literal token.
- Lit = Actions.ActOnUnaryOp(getCurScope(), OpLoc, Kind, Lit.take());
+ Lit = Actions.ActOnUnaryOp(getCurScope(), OpLoc, Kind, Lit.get());
if (Lit.isInvalid())
return Lit;
return ParsePostfixExpressionSuffix(
- Actions.BuildObjCNumericLiteral(AtLoc, Lit.take()));
+ Actions.BuildObjCNumericLiteral(AtLoc, Lit.get()));
}
case tok::string_literal: // primary-expression: string-literal
@@ -2155,7 +2154,7 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
return ParsePostfixExpressionSuffix(ParseObjCBoxedExpr(AtLoc));
default:
- if (Tok.getIdentifierInfo() == 0)
+ if (Tok.getIdentifierInfo() == nullptr)
return ExprError(Diag(AtLoc, diag::err_unexpected_at));
switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {
@@ -2166,13 +2165,13 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
case tok::objc_selector:
return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc));
default: {
- const char *str = 0;
+ const char *str = nullptr;
if (GetLookAheadToken(1).is(tok::l_brace)) {
char ch = Tok.getIdentifierInfo()->getNameStart()[0];
str =
ch == 't' ? "try"
: (ch == 'f' ? "finally"
- : (ch == 'a' ? "autoreleasepool" : 0));
+ : (ch == 'a' ? "autoreleasepool" : nullptr));
}
if (str) {
SourceLocation kwLoc = Tok.getLocation();
@@ -2223,7 +2222,7 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
return true;
IsExpr = true;
- TypeOrExpr = Receiver.take();
+ TypeOrExpr = Receiver.get();
return false;
}
@@ -2249,14 +2248,14 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
// instance method.
ExprResult Receiver = ParseCXXTypeConstructExpression(DS);
if (!Receiver.isInvalid())
- Receiver = ParsePostfixExpressionSuffix(Receiver.take());
+ Receiver = ParsePostfixExpressionSuffix(Receiver.get());
if (!Receiver.isInvalid())
- Receiver = ParseRHSOfBinaryExpression(Receiver.take(), prec::Comma);
+ Receiver = ParseRHSOfBinaryExpression(Receiver.get(), prec::Comma);
if (Receiver.isInvalid())
return true;
IsExpr = true;
- TypeOrExpr = Receiver.take();
+ TypeOrExpr = Receiver.get();
return false;
}
@@ -2345,11 +2344,11 @@ ExprResult Parser::ParseObjCMessageExpression() {
if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super &&
NextToken().isNot(tok::period) && getCurScope()->isInObjcMethodScope())
return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(),
- ParsedType(), 0);
+ ParsedType(), nullptr);
// Parse the receiver, which is either a type or an expression.
bool IsExpr;
- void *TypeOrExpr = NULL;
+ void *TypeOrExpr = nullptr;
if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) {
SkipUntil(tok::r_square, StopAtSemi);
return ExprError();
@@ -2362,7 +2361,7 @@ ExprResult Parser::ParseObjCMessageExpression() {
return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
ParsedType::getFromOpaquePtr(TypeOrExpr),
- 0);
+ nullptr);
}
if (Tok.is(tok::identifier)) {
@@ -2375,7 +2374,7 @@ ExprResult Parser::ParseObjCMessageExpression() {
ReceiverType)) {
case Sema::ObjCSuperMessage:
return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(),
- ParsedType(), 0);
+ ParsedType(), nullptr);
case Sema::ObjCClassMessage:
if (!ReceiverType) {
@@ -2386,8 +2385,8 @@ ExprResult Parser::ParseObjCMessageExpression() {
ConsumeToken(); // the type name
return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
- ReceiverType, 0);
-
+ ReceiverType, nullptr);
+
case Sema::ObjCInstanceMessage:
// Fall through to parse an expression.
break;
@@ -2402,7 +2401,7 @@ ExprResult Parser::ParseObjCMessageExpression() {
}
return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
- ParsedType(), Res.take());
+ ParsedType(), Res.get());
}
/// \brief Parse the remainder of an Objective-C message following the
@@ -2478,8 +2477,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
KeyIdents.push_back(selIdent);
KeyLocs.push_back(Loc);
- if (Tok.isNot(tok::colon)) {
- Diag(Tok, diag::err_expected_colon);
+ if (ExpectAndConsume(tok::colon)) {
// We must manually skip to a ']', otherwise the expression skipper will
// stop at the ']' when it skips to the ';'. We want it to skip beyond
// the enclosing expression.
@@ -2487,7 +2485,6 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
return ExprError();
}
- ConsumeToken(); // Eat the ':'.
/// Parse the expression after ':'
if (Tok.is(tok::code_completion)) {
@@ -2525,7 +2522,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
}
// We have a valid expression.
- KeyExprs.push_back(Res.release());
+ KeyExprs.push_back(Res.get());
// Code completion after each argument.
if (Tok.is(tok::code_completion)) {
@@ -2569,10 +2566,10 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
}
// We have a valid expression.
- KeyExprs.push_back(Res.release());
+ KeyExprs.push_back(Res.get());
}
} else if (!selIdent) {
- Diag(Tok, diag::err_expected_ident); // missing selector name.
+ Diag(Tok, diag::err_expected) << tok::identifier; // missing selector name.
// We must manually skip to a ']', otherwise the expression skipper will
// stop at the ']' when it skips to the ';'. We want it to skip beyond
@@ -2582,10 +2579,8 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
}
if (Tok.isNot(tok::r_square)) {
- if (Tok.is(tok::identifier))
- Diag(Tok, diag::err_expected_colon);
- else
- Diag(Tok, diag::err_expected_rsquare);
+ Diag(Tok, diag::err_expected)
+ << (Tok.is(tok::identifier) ? tok::colon : tok::r_square);
// We must manually skip to a ']', otherwise the expression skipper will
// stop at the ']' when it skips to the ';'. We want it to skip beyond
// the enclosing expression.
@@ -2622,7 +2617,7 @@ ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
SmallVector<SourceLocation, 4> AtLocs;
ExprVector AtStrings;
AtLocs.push_back(AtLoc);
- AtStrings.push_back(Res.release());
+ AtStrings.push_back(Res.get());
while (Tok.is(tok::at)) {
AtLocs.push_back(ConsumeToken()); // eat the @.
@@ -2635,7 +2630,7 @@ ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
if (Lit.isInvalid())
return Lit;
- AtStrings.push_back(Lit.release());
+ AtStrings.push_back(Lit.get());
}
return Actions.ParseObjCStringLiteral(&AtLocs[0], AtStrings.data(),
@@ -2662,7 +2657,7 @@ ExprResult Parser::ParseObjCCharacterLiteral(SourceLocation AtLoc) {
return Lit;
}
ConsumeToken(); // Consume the literal token.
- return Actions.BuildObjCNumericLiteral(AtLoc, Lit.take());
+ return Actions.BuildObjCNumericLiteral(AtLoc, Lit.get());
}
/// ParseObjCNumericLiteral -
@@ -2676,7 +2671,7 @@ ExprResult Parser::ParseObjCNumericLiteral(SourceLocation AtLoc) {
return Lit;
}
ConsumeToken(); // Consume the literal token.
- return Actions.BuildObjCNumericLiteral(AtLoc, Lit.take());
+ return Actions.BuildObjCNumericLiteral(AtLoc, Lit.get());
}
/// ParseObjCBoxedExpr -
@@ -2699,9 +2694,9 @@ Parser::ParseObjCBoxedExpr(SourceLocation AtLoc) {
// Wrap the sub-expression in a parenthesized expression, to distinguish
// a boxed expression from a literal.
SourceLocation LPLoc = T.getOpenLocation(), RPLoc = T.getCloseLocation();
- ValueExpr = Actions.ActOnParenExpr(LPLoc, RPLoc, ValueExpr.take());
+ ValueExpr = Actions.ActOnParenExpr(LPLoc, RPLoc, ValueExpr.get());
return Actions.BuildObjCBoxedExpr(SourceRange(AtLoc, RPLoc),
- ValueExpr.take());
+ ValueExpr.get());
}
ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) {
@@ -2725,12 +2720,13 @@ ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) {
if (Res.isInvalid())
return true;
- ElementExprs.push_back(Res.release());
+ ElementExprs.push_back(Res.get());
if (Tok.is(tok::comma))
ConsumeToken(); // Eat the ','.
else if (Tok.isNot(tok::r_square))
- return ExprError(Diag(Tok, diag::err_expected_rsquare_or_comma));
+ return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_square
+ << tok::comma);
}
SourceLocation EndLoc = ConsumeBracket(); // location of ']'
MultiExprArg Args(ElementExprs);
@@ -2755,10 +2751,7 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
}
}
- if (Tok.is(tok::colon)) {
- ConsumeToken();
- } else {
- Diag(Tok, diag::err_expected_colon);
+ if (ExpectAndConsume(tok::colon)) {
SkipUntil(tok::r_brace, StopAtSemi);
return ExprError();
}
@@ -2774,20 +2767,19 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
// Parse the ellipsis that designates this as a pack expansion.
SourceLocation EllipsisLoc;
- if (Tok.is(tok::ellipsis) && getLangOpts().CPlusPlus)
- EllipsisLoc = ConsumeToken();
-
+ if (getLangOpts().CPlusPlus)
+ TryConsumeToken(tok::ellipsis, EllipsisLoc);
+
// We have a valid expression. Collect it in a vector so we can
// build the argument list.
ObjCDictionaryElement Element = {
KeyExpr.get(), ValueExpr.get(), EllipsisLoc, None
};
Elements.push_back(Element);
-
- if (Tok.is(tok::comma))
- ConsumeToken(); // Eat the ','.
- else if (Tok.isNot(tok::r_brace))
- return ExprError(Diag(Tok, diag::err_expected_rbrace_or_comma));
+
+ if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace))
+ return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_brace
+ << tok::comma);
}
SourceLocation EndLoc = ConsumeBrace();
@@ -2834,7 +2826,7 @@ Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
T.consumeOpen();
if (Tok.isNot(tok::identifier))
- return ExprError(Diag(Tok, diag::err_expected_ident));
+ return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);
IdentifierInfo *protocolId = Tok.getIdentifierInfo();
SourceLocation ProtoIdLoc = ConsumeToken();
@@ -2847,7 +2839,7 @@ Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
}
/// objc-selector-expression
-/// @selector '(' objc-keyword-selector ')'
+/// @selector '(' '('[opt] objc-keyword-selector ')'[opt] ')'
ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
SourceLocation SelectorLoc = ConsumeToken();
@@ -2859,7 +2851,10 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
-
+ bool HasOptionalParen = Tok.is(tok::l_paren);
+ if (HasOptionalParen)
+ ConsumeParen();
+
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents);
cutOffParsing();
@@ -2869,20 +2864,20 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc);
if (!SelIdent && // missing selector name.
Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon))
- return ExprError(Diag(Tok, diag::err_expected_ident));
+ return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);
KeyIdents.push_back(SelIdent);
+
unsigned nColons = 0;
if (Tok.isNot(tok::r_paren)) {
while (1) {
- if (Tok.is(tok::coloncolon)) { // Handle :: in C++.
+ if (TryConsumeToken(tok::coloncolon)) { // Handle :: in C++.
++nColons;
- KeyIdents.push_back(0);
- } else if (Tok.isNot(tok::colon))
- return ExprError(Diag(Tok, diag::err_expected_colon));
-
+ KeyIdents.push_back(nullptr);
+ } else if (ExpectAndConsume(tok::colon)) // Otherwise expect ':'.
+ return ExprError();
++nColons;
- ConsumeToken(); // Eat the ':' or '::'.
+
if (Tok.is(tok::r_paren))
break;
@@ -2900,11 +2895,14 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
break;
}
}
+ if (HasOptionalParen && Tok.is(tok::r_paren))
+ ConsumeParen(); // ')'
T.consumeClose();
Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]);
return Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc,
T.getOpenLocation(),
- T.getCloseLocation());
+ T.getCloseLocation(),
+ !HasOptionalParen);
}
void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
@@ -2931,7 +2929,7 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
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 ':'");
- // Enter a scope for the method or c-fucntion body.
+ // Enter a scope for the method or c-function body.
ParseScope BodyScope(this,
parseMethod
? Scope::ObjCMethodScope|Scope::FnScope|Scope::DeclScope
@@ -2944,11 +2942,11 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
else
Actions.ActOnStartOfFunctionDef(getCurScope(), MCDecl);
if (Tok.is(tok::kw_try))
- MCDecl = ParseFunctionTryBlock(MCDecl, BodyScope);
+ ParseFunctionTryBlock(MCDecl, BodyScope);
else {
if (Tok.is(tok::colon))
ParseConstructorInitializer(MCDecl);
- MCDecl = ParseFunctionStatementBody(MCDecl, BodyScope);
+ ParseFunctionStatementBody(MCDecl, BodyScope);
}
if (Tok.getLocation() != OrigLoc) {
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index 89e4147e285c..d1544e6baa5b 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/lib/Parse/ParseOpenMP.cpp
@@ -11,19 +11,43 @@
///
//===----------------------------------------------------------------------===//
+#include "RAIIObjectsForParser.h"
#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/PointerIntPair.h"
-#include "RAIIObjectsForParser.h"
using namespace clang;
//===----------------------------------------------------------------------===//
// OpenMP declarative directives.
//===----------------------------------------------------------------------===//
+static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
+ auto Tok = P.getCurToken();
+ auto DKind =
+ Tok.isAnnotation()
+ ? OMPD_unknown
+ : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
+ if (DKind == OMPD_parallel) {
+ Tok = P.getPreprocessor().LookAhead(0);
+ auto SDKind =
+ Tok.isAnnotation()
+ ? OMPD_unknown
+ : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
+ if (SDKind == OMPD_for) {
+ P.ConsumeToken();
+ DKind = OMPD_parallel_for;
+ } else if (SDKind == OMPD_sections) {
+ P.ConsumeToken();
+ DKind = OMPD_parallel_sections;
+ }
+ }
+ return DKind;
+}
+
/// \brief Parsing of declarative OpenMP directives.
///
/// threadprivate-directive:
@@ -35,9 +59,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
SourceLocation Loc = ConsumeToken();
SmallVector<Expr *, 5> Identifiers;
- OpenMPDirectiveKind DKind = Tok.isAnnotation() ?
- OMPD_unknown :
- getOpenMPDirectiveKind(PP.getSpelling(Tok));
+ auto DKind = ParseOpenMPDirectiveKind(*this);
switch (DKind) {
case OMPD_threadprivate:
@@ -47,23 +69,34 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
// extra tokens.
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
- << getOpenMPDirectiveName(OMPD_threadprivate);
+ << getOpenMPDirectiveName(OMPD_threadprivate);
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
}
// Skip the last annot_pragma_openmp_end.
ConsumeToken();
- return Actions.ActOnOpenMPThreadprivateDirective(Loc,
- Identifiers);
+ return Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
}
break;
case OMPD_unknown:
Diag(Tok, diag::err_omp_unknown_directive);
break;
case OMPD_parallel:
+ case OMPD_simd:
case OMPD_task:
- case NUM_OPENMP_DIRECTIVES:
+ case OMPD_taskyield:
+ case OMPD_barrier:
+ case OMPD_taskwait:
+ case OMPD_flush:
+ case OMPD_for:
+ case OMPD_sections:
+ case OMPD_section:
+ case OMPD_single:
+ case OMPD_master:
+ case OMPD_critical:
+ case OMPD_parallel_for:
+ case OMPD_parallel_sections:
Diag(Tok, diag::err_omp_unexpected_directive)
- << getOpenMPDirectiveName(DKind);
+ << getOpenMPDirectiveName(DKind);
break;
}
SkipUntil(tok::annot_pragma_openmp_end);
@@ -76,25 +109,29 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
/// annot_pragma_openmp 'threadprivate' simple-variable-list
/// annot_pragma_openmp_end
///
-/// parallel-directive:
-/// annot_pragma_openmp 'parallel' {clause} annot_pragma_openmp_end
+/// executable-directive:
+/// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
+/// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
+/// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
+/// 'barrier' | 'taskwait' | 'flush' {clause} annot_pragma_openmp_end
///
-StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
+StmtResult
+Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
ParenBraceBracketBalancer BalancerRAIIObj(*this);
SmallVector<Expr *, 5> Identifiers;
SmallVector<OMPClause *, 5> Clauses;
- SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, NUM_OPENMP_CLAUSES>
- FirstClauses(NUM_OPENMP_CLAUSES);
- const unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
- Scope::OpenMPDirectiveScope;
+ SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
+ FirstClauses(OMPC_unknown + 1);
+ unsigned ScopeFlags =
+ Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope;
SourceLocation Loc = ConsumeToken(), EndLoc;
- OpenMPDirectiveKind DKind = Tok.isAnnotation() ?
- OMPD_unknown :
- getOpenMPDirectiveKind(PP.getSpelling(Tok));
+ auto DKind = ParseOpenMPDirectiveKind(*this);
// Name of critical directive.
DeclarationNameInfo DirName;
StmtResult Directive = StmtError();
+ bool HasAssociatedStatement = true;
+ bool FlushHasClause = false;
switch (DKind) {
case OMPD_threadprivate:
@@ -104,27 +141,75 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
// extra tokens.
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
- << getOpenMPDirectiveName(OMPD_threadprivate);
+ << getOpenMPDirectiveName(OMPD_threadprivate);
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
}
DeclGroupPtrTy Res =
- Actions.ActOnOpenMPThreadprivateDirective(Loc,
- Identifiers);
+ Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
}
SkipUntil(tok::annot_pragma_openmp_end);
break;
- case OMPD_parallel: {
+ case OMPD_flush:
+ if (PP.LookAhead(0).is(tok::l_paren)) {
+ FlushHasClause = true;
+ // Push copy of the current token back to stream to properly parse
+ // pseudo-clause OMPFlushClause.
+ PP.EnterToken(Tok);
+ }
+ case OMPD_taskyield:
+ case OMPD_barrier:
+ case OMPD_taskwait:
+ if (!StandAloneAllowed) {
+ Diag(Tok, diag::err_omp_immediate_directive)
+ << getOpenMPDirectiveName(DKind);
+ }
+ HasAssociatedStatement = false;
+ // Fall through for further analysis.
+ case OMPD_parallel:
+ case OMPD_simd:
+ case OMPD_for:
+ case OMPD_sections:
+ case OMPD_single:
+ case OMPD_section:
+ case OMPD_master:
+ case OMPD_critical:
+ case OMPD_parallel_for:
+ case OMPD_parallel_sections:
+ case OMPD_task: {
ConsumeToken();
+ // Parse directive name of the 'critical' directive if any.
+ if (DKind == OMPD_critical) {
+ BalancedDelimiterTracker T(*this, tok::l_paren,
+ tok::annot_pragma_openmp_end);
+ if (!T.consumeOpen()) {
+ if (Tok.isAnyIdentifier()) {
+ DirName =
+ DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
+ ConsumeAnyToken();
+ } else {
+ Diag(Tok, diag::err_omp_expected_identifier_for_critical);
+ }
+ T.consumeClose();
+ }
+ }
- Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope());
+ if (isOpenMPLoopDirective(DKind))
+ ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
+ if (isOpenMPSimdDirective(DKind))
+ ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
+ ParseScope OMPDirectiveScope(this, ScopeFlags);
+ Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
- OpenMPClauseKind CKind = Tok.isAnnotation() ?
- OMPC_unknown :
- getOpenMPClauseKind(PP.getSpelling(Tok));
- OMPClause *Clause = ParseOpenMPClause(DKind, CKind,
- !FirstClauses[CKind].getInt());
+ OpenMPClauseKind CKind =
+ Tok.isAnnotation()
+ ? OMPC_unknown
+ : FlushHasClause ? OMPC_flush
+ : getOpenMPClauseKind(PP.getSpelling(Tok));
+ FlushHasClause = false;
+ OMPClause *Clause =
+ ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
FirstClauses[CKind].setInt(true);
if (Clause) {
FirstClauses[CKind].setPointer(Clause);
@@ -142,11 +227,10 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
StmtResult AssociatedStmt;
bool CreateDirective = true;
- ParseScope OMPDirectiveScope(this, ScopeFlags);
- {
+ if (HasAssociatedStatement) {
// The body is a block scope like in Lambdas and Blocks.
Sema::CompoundScopeRAII CompoundScope(Actions);
- Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_OpenMP, 1);
+ Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
Actions.ActOnStartOfCompoundStmt();
// Parse statement
AssociatedStmt = ParseStatement();
@@ -155,30 +239,23 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
Actions.ActOnCapturedRegionError();
CreateDirective = false;
} else {
- AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.take());
+ AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.get());
CreateDirective = AssociatedStmt.isUsable();
}
}
if (CreateDirective)
- Directive = Actions.ActOnOpenMPExecutableDirective(DKind, Clauses,
- AssociatedStmt.take(),
- Loc, EndLoc);
+ Directive = Actions.ActOnOpenMPExecutableDirective(
+ DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);
// Exit scope.
Actions.EndOpenMPDSABlock(Directive.get());
OMPDirectiveScope.Exit();
- }
break;
+ }
case OMPD_unknown:
Diag(Tok, diag::err_omp_unknown_directive);
SkipUntil(tok::annot_pragma_openmp_end);
break;
- case OMPD_task:
- case NUM_OPENMP_DIRECTIVES:
- Diag(Tok, diag::err_omp_unexpected_directive)
- << getOpenMPDirectiveName(DKind);
- SkipUntil(tok::annot_pragma_openmp_end);
- break;
}
return Directive;
}
@@ -225,14 +302,15 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
IsCorrect = false;
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
- Diag(PrevTok.getLocation(), diag::err_expected_ident)
- << SourceRange(PrevTok.getLocation(), PrevTokLocation);
+ Diag(PrevTok.getLocation(), diag::err_expected)
+ << tok::identifier
+ << SourceRange(PrevTok.getLocation(), PrevTokLocation);
} else {
DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
- ExprResult Res = Actions.ActOnOpenMPIdExpression(getCurScope(), SS,
- NameInfo);
+ ExprResult Res =
+ Actions.ActOnOpenMPIdExpression(getCurScope(), SS, NameInfo);
if (Res.isUsable())
- VarList.push_back(Res.take());
+ VarList.push_back(Res.get());
}
// Consume ','.
if (Tok.is(tok::comma)) {
@@ -241,7 +319,7 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
}
if (NoIdentIsFound) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
IsCorrect = false;
}
@@ -254,56 +332,159 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
/// \brief Parsing of OpenMP clauses.
///
/// clause:
-/// default-clause|private-clause|firstprivate-clause|shared-clause
+/// if-clause | final-clause | num_threads-clause | safelen-clause |
+/// default-clause | private-clause | firstprivate-clause | shared-clause
+/// | linear-clause | aligned-clause | collapse-clause |
+/// lastprivate-clause | reduction-clause | proc_bind-clause |
+/// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
+/// mergeable-clause | flush-clause
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind, bool FirstClause) {
- OMPClause *Clause = 0;
+ OMPClause *Clause = nullptr;
bool ErrorFound = false;
// Check if clause is allowed for the given directive.
if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
- Diag(Tok, diag::err_omp_unexpected_clause)
- << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
+ Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
+ << getOpenMPDirectiveName(DKind);
ErrorFound = true;
}
switch (CKind) {
+ case OMPC_if:
+ case OMPC_final:
+ case OMPC_num_threads:
+ case OMPC_safelen:
+ case OMPC_collapse:
+ // OpenMP [2.5, Restrictions]
+ // At most one if clause can appear on the directive.
+ // At most one num_threads clause can appear on the directive.
+ // OpenMP [2.8.1, simd construct, Restrictions]
+ // Only one safelen clause can appear on a simd directive.
+ // Only one collapse clause can appear on a simd directive.
+ // OpenMP [2.11.1, task Construct, Restrictions]
+ // At most one if clause can appear on the directive.
+ // At most one final clause can appear on the directive.
+ if (!FirstClause) {
+ Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
+ << getOpenMPClauseName(CKind);
+ }
+
+ Clause = ParseOpenMPSingleExprClause(CKind);
+ break;
case OMPC_default:
- // OpenMP [2.9.3.1, Restrictions]
- // Only a single default clause may be specified on a parallel or task
- // directive.
+ case OMPC_proc_bind:
+ // OpenMP [2.14.3.1, Restrictions]
+ // Only a single default clause may be specified on a parallel, task or
+ // teams directive.
+ // OpenMP [2.5, parallel Construct, Restrictions]
+ // At most one proc_bind clause can appear on the directive.
if (!FirstClause) {
- Diag(Tok, diag::err_omp_more_one_clause)
- << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
+ Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
+ << getOpenMPClauseName(CKind);
}
Clause = ParseOpenMPSimpleClause(CKind);
break;
+ case OMPC_schedule:
+ // OpenMP [2.7.1, Restrictions, p. 3]
+ // Only one schedule clause can appear on a loop directive.
+ if (!FirstClause) {
+ Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
+ << getOpenMPClauseName(CKind);
+ }
+
+ Clause = ParseOpenMPSingleExprWithArgClause(CKind);
+ break;
+ case OMPC_ordered:
+ case OMPC_nowait:
+ case OMPC_untied:
+ case OMPC_mergeable:
+ // OpenMP [2.7.1, Restrictions, p. 9]
+ // Only one ordered clause can appear on a loop directive.
+ // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
+ // Only one nowait clause can appear on a for directive.
+ if (!FirstClause) {
+ Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
+ << getOpenMPClauseName(CKind);
+ }
+
+ Clause = ParseOpenMPClause(CKind);
+ break;
case OMPC_private:
case OMPC_firstprivate:
+ case OMPC_lastprivate:
case OMPC_shared:
+ case OMPC_reduction:
+ case OMPC_linear:
+ case OMPC_aligned:
+ case OMPC_copyin:
+ case OMPC_copyprivate:
+ case OMPC_flush:
Clause = ParseOpenMPVarListClause(CKind);
break;
case OMPC_unknown:
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
- << getOpenMPDirectiveName(DKind);
+ << getOpenMPDirectiveName(DKind);
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
break;
case OMPC_threadprivate:
- case NUM_OPENMP_CLAUSES:
- Diag(Tok, diag::err_omp_unexpected_clause)
- << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
+ Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
+ << getOpenMPDirectiveName(DKind);
SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
break;
}
- return ErrorFound ? 0 : Clause;
+ return ErrorFound ? nullptr : Clause;
+}
+
+/// \brief Parsing of OpenMP clauses with single expressions like 'if',
+/// 'final', 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams' or
+/// 'thread_limit'.
+///
+/// if-clause:
+/// 'if' '(' expression ')'
+///
+/// final-clause:
+/// 'final' '(' expression ')'
+///
+/// num_threads-clause:
+/// 'num_threads' '(' expression ')'
+///
+/// safelen-clause:
+/// 'safelen' '(' expression ')'
+///
+/// collapse-clause:
+/// 'collapse' '(' expression ')'
+///
+OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
+ SourceLocation Loc = ConsumeToken();
+
+ BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
+ if (T.expectAndConsume(diag::err_expected_lparen_after,
+ getOpenMPClauseName(Kind)))
+ return nullptr;
+
+ ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
+ ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
+
+ // Parse ')'.
+ T.consumeClose();
+
+ if (Val.isInvalid())
+ return nullptr;
+
+ return Actions.ActOnOpenMPSingleExprClause(
+ Kind, Val.get(), Loc, T.getOpenLocation(), T.getCloseLocation());
}
-/// \brief Parsing of simple OpenMP clauses like 'default'.
+/// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
///
/// default-clause:
/// 'default' '(' 'none' | 'shared' ')
///
+/// proc_bind-clause:
+/// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
+///
OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
SourceLocation Loc = Tok.getLocation();
SourceLocation LOpen = ConsumeToken();
@@ -311,11 +492,10 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
if (T.expectAndConsume(diag::err_expected_lparen_after,
getOpenMPClauseName(Kind)))
- return 0;
+ return nullptr;
- unsigned Type = Tok.isAnnotation() ?
- unsigned(OMPC_DEFAULT_unknown) :
- getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok));
+ unsigned Type = getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
SourceLocation TypeLoc = Tok.getLocation();
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
Tok.isNot(tok::annot_pragma_openmp_end))
@@ -328,54 +508,221 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
Tok.getLocation());
}
-/// \brief Parsing of OpenMP clause 'private', 'firstprivate',
-/// 'shared', 'copyin', or 'reduction'.
+/// \brief Parsing of OpenMP clauses like 'ordered'.
+///
+/// ordered-clause:
+/// 'ordered'
+///
+/// nowait-clause:
+/// 'nowait'
+///
+/// untied-clause:
+/// 'untied'
+///
+/// mergeable-clause:
+/// 'mergeable'
+///
+OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
+ SourceLocation Loc = Tok.getLocation();
+ ConsumeAnyToken();
+
+ return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
+}
+
+
+/// \brief Parsing of OpenMP clauses with single expressions and some additional
+/// argument like 'schedule' or 'dist_schedule'.
+///
+/// schedule-clause:
+/// 'schedule' '(' kind [',' expression ] ')'
+///
+OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
+ SourceLocation Loc = ConsumeToken();
+ SourceLocation CommaLoc;
+ // Parse '('.
+ BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
+ if (T.expectAndConsume(diag::err_expected_lparen_after,
+ getOpenMPClauseName(Kind)))
+ return nullptr;
+
+ ExprResult Val;
+ unsigned Type = getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
+ SourceLocation KLoc = Tok.getLocation();
+ if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
+ Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
+
+ if (Kind == OMPC_schedule &&
+ (Type == OMPC_SCHEDULE_static || Type == OMPC_SCHEDULE_dynamic ||
+ Type == OMPC_SCHEDULE_guided) &&
+ Tok.is(tok::comma)) {
+ CommaLoc = ConsumeAnyToken();
+ ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
+ Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
+ if (Val.isInvalid())
+ return nullptr;
+ }
+
+ // Parse ')'.
+ T.consumeClose();
+
+ return Actions.ActOnOpenMPSingleExprWithArgClause(
+ Kind, Type, Val.get(), Loc, T.getOpenLocation(), KLoc, CommaLoc,
+ T.getCloseLocation());
+}
+
+static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
+ UnqualifiedId &ReductionId) {
+ SourceLocation TemplateKWLoc;
+ if (ReductionIdScopeSpec.isEmpty()) {
+ auto OOK = OO_None;
+ switch (P.getCurToken().getKind()) {
+ case tok::plus:
+ OOK = OO_Plus;
+ break;
+ case tok::minus:
+ OOK = OO_Minus;
+ break;
+ case tok::star:
+ OOK = OO_Star;
+ break;
+ case tok::amp:
+ OOK = OO_Amp;
+ break;
+ case tok::pipe:
+ OOK = OO_Pipe;
+ break;
+ case tok::caret:
+ OOK = OO_Caret;
+ break;
+ case tok::ampamp:
+ OOK = OO_AmpAmp;
+ break;
+ case tok::pipepipe:
+ OOK = OO_PipePipe;
+ break;
+ default:
+ break;
+ }
+ if (OOK != OO_None) {
+ SourceLocation OpLoc = P.ConsumeToken();
+ SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
+ ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
+ return false;
+ }
+ }
+ return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
+ /*AllowDestructorName*/ false,
+ /*AllowConstructorName*/ false, ParsedType(),
+ TemplateKWLoc, ReductionId);
+}
+
+/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
+/// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'.
///
/// private-clause:
/// 'private' '(' list ')'
/// firstprivate-clause:
/// 'firstprivate' '(' list ')'
+/// lastprivate-clause:
+/// 'lastprivate' '(' list ')'
/// shared-clause:
/// 'shared' '(' list ')'
+/// linear-clause:
+/// 'linear' '(' list [ ':' linear-step ] ')'
+/// aligned-clause:
+/// 'aligned' '(' list [ ':' alignment ] ')'
+/// reduction-clause:
+/// 'reduction' '(' reduction-identifier ':' list ')'
+/// copyprivate-clause:
+/// 'copyprivate' '(' list ')'
+/// flush-clause:
+/// 'flush' '(' list ')'
///
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
SourceLocation Loc = Tok.getLocation();
SourceLocation LOpen = ConsumeToken();
+ SourceLocation ColonLoc = SourceLocation();
+ // Optional scope specifier and unqualified id for reduction identifier.
+ CXXScopeSpec ReductionIdScopeSpec;
+ UnqualifiedId ReductionId;
+ bool InvalidReductionId = false;
// Parse '('.
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
if (T.expectAndConsume(diag::err_expected_lparen_after,
getOpenMPClauseName(Kind)))
- return 0;
+ return nullptr;
+
+ // Handle reduction-identifier for reduction clause.
+ if (Kind == OMPC_reduction) {
+ ColonProtectionRAIIObject ColonRAII(*this);
+ if (getLangOpts().CPlusPlus) {
+ ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, ParsedType(), false);
+ }
+ InvalidReductionId =
+ ParseReductionId(*this, ReductionIdScopeSpec, ReductionId);
+ if (InvalidReductionId) {
+ SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ }
+ if (Tok.is(tok::colon)) {
+ ColonLoc = ConsumeToken();
+ } else {
+ Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
+ }
+ }
SmallVector<Expr *, 5> Vars;
- bool IsComma = true;
- while (IsComma || (Tok.isNot(tok::r_paren) &&
+ bool IsComma = !InvalidReductionId;
+ const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
+ while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
Tok.isNot(tok::annot_pragma_openmp_end))) {
+ ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
// Parse variable
ExprResult VarExpr = ParseAssignmentExpression();
if (VarExpr.isUsable()) {
- Vars.push_back(VarExpr.take());
+ Vars.push_back(VarExpr.get());
} else {
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
}
// Skip ',' if any
IsComma = Tok.is(tok::comma);
- if (IsComma) {
+ if (IsComma)
ConsumeToken();
- } else if (Tok.isNot(tok::r_paren) &&
- Tok.isNot(tok::annot_pragma_openmp_end)) {
+ else if (Tok.isNot(tok::r_paren) &&
+ Tok.isNot(tok::annot_pragma_openmp_end) &&
+ (!MayHaveTail || Tok.isNot(tok::colon)))
Diag(Tok, diag::err_omp_expected_punc)
- << 1 << getOpenMPClauseName(Kind);
- }
+ << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
+ : getOpenMPClauseName(Kind))
+ << (Kind == OMPC_flush);
+ }
+
+ // Parse ':' linear-step (or ':' alignment).
+ Expr *TailExpr = nullptr;
+ const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
+ if (MustHaveTail) {
+ ColonLoc = Tok.getLocation();
+ ConsumeToken();
+ ExprResult Tail = ParseAssignmentExpression();
+ if (Tail.isUsable())
+ TailExpr = Tail.get();
+ else
+ SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
}
// Parse ')'.
T.consumeClose();
- if (Vars.empty())
- return 0;
+ if (Vars.empty() || (MustHaveTail && !TailExpr) || InvalidReductionId)
+ return nullptr;
- return Actions.ActOnOpenMPVarListClause(Kind, Vars, Loc, LOpen,
- Tok.getLocation());
+ return Actions.ActOnOpenMPVarListClause(
+ Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
+ ReductionIdScopeSpec,
+ ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
+ : DeclarationNameInfo());
}
diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp
index 8a374e0fce61..d3777f3ea4a0 100644
--- a/lib/Parse/ParsePragma.cpp
+++ b/lib/Parse/ParsePragma.cpp
@@ -11,14 +11,288 @@
//
//===----------------------------------------------------------------------===//
-#include "ParsePragma.h"
+#include "RAIIObjectsForParser.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
+#include "clang/Sema/LoopHint.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
+namespace {
+
+struct PragmaAlignHandler : public PragmaHandler {
+ explicit PragmaAlignHandler() : PragmaHandler("align") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaGCCVisibilityHandler : public PragmaHandler {
+ explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaOptionsHandler : public PragmaHandler {
+ explicit PragmaOptionsHandler() : PragmaHandler("options") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaPackHandler : public PragmaHandler {
+ explicit PragmaPackHandler() : PragmaHandler("pack") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaMSStructHandler : public PragmaHandler {
+ explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaUnusedHandler : public PragmaHandler {
+ PragmaUnusedHandler() : PragmaHandler("unused") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaWeakHandler : public PragmaHandler {
+ explicit PragmaWeakHandler() : PragmaHandler("weak") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaRedefineExtnameHandler : public PragmaHandler {
+ explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaOpenCLExtensionHandler : public PragmaHandler {
+ PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+
+struct PragmaFPContractHandler : public PragmaHandler {
+ PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaNoOpenMPHandler : public PragmaHandler {
+ PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaOpenMPHandler : public PragmaHandler {
+ PragmaOpenMPHandler() : PragmaHandler("omp") { }
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+/// PragmaCommentHandler - "\#pragma comment ...".
+struct PragmaCommentHandler : public PragmaHandler {
+ PragmaCommentHandler(Sema &Actions)
+ : PragmaHandler("comment"), Actions(Actions) {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+private:
+ Sema &Actions;
+};
+
+struct PragmaDetectMismatchHandler : public PragmaHandler {
+ PragmaDetectMismatchHandler(Sema &Actions)
+ : PragmaHandler("detect_mismatch"), Actions(Actions) {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+private:
+ Sema &Actions;
+};
+
+struct PragmaMSPointersToMembers : public PragmaHandler {
+ explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaMSVtorDisp : public PragmaHandler {
+ explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaMSPragma : public PragmaHandler {
+ explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+/// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
+struct PragmaOptimizeHandler : public PragmaHandler {
+ PragmaOptimizeHandler(Sema &S)
+ : PragmaHandler("optimize"), Actions(S) {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+private:
+ Sema &Actions;
+};
+
+struct PragmaLoopHintHandler : public PragmaHandler {
+ PragmaLoopHintHandler() : PragmaHandler("loop") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaUnrollHintHandler : public PragmaHandler {
+ PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+} // end namespace
+
+void Parser::initializePragmaHandlers() {
+ AlignHandler.reset(new PragmaAlignHandler());
+ PP.AddPragmaHandler(AlignHandler.get());
+
+ GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
+ PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
+
+ OptionsHandler.reset(new PragmaOptionsHandler());
+ PP.AddPragmaHandler(OptionsHandler.get());
+
+ PackHandler.reset(new PragmaPackHandler());
+ PP.AddPragmaHandler(PackHandler.get());
+
+ MSStructHandler.reset(new PragmaMSStructHandler());
+ PP.AddPragmaHandler(MSStructHandler.get());
+
+ UnusedHandler.reset(new PragmaUnusedHandler());
+ PP.AddPragmaHandler(UnusedHandler.get());
+
+ WeakHandler.reset(new PragmaWeakHandler());
+ PP.AddPragmaHandler(WeakHandler.get());
+
+ RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
+ PP.AddPragmaHandler(RedefineExtnameHandler.get());
+
+ FPContractHandler.reset(new PragmaFPContractHandler());
+ PP.AddPragmaHandler("STDC", FPContractHandler.get());
+
+ if (getLangOpts().OpenCL) {
+ OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
+ PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
+
+ PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
+ }
+ if (getLangOpts().OpenMP)
+ OpenMPHandler.reset(new PragmaOpenMPHandler());
+ else
+ OpenMPHandler.reset(new PragmaNoOpenMPHandler());
+ PP.AddPragmaHandler(OpenMPHandler.get());
+
+ if (getLangOpts().MicrosoftExt) {
+ MSCommentHandler.reset(new PragmaCommentHandler(Actions));
+ PP.AddPragmaHandler(MSCommentHandler.get());
+ MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
+ PP.AddPragmaHandler(MSDetectMismatchHandler.get());
+ MSPointersToMembers.reset(new PragmaMSPointersToMembers());
+ PP.AddPragmaHandler(MSPointersToMembers.get());
+ MSVtorDisp.reset(new PragmaMSVtorDisp());
+ PP.AddPragmaHandler(MSVtorDisp.get());
+ MSInitSeg.reset(new PragmaMSPragma("init_seg"));
+ PP.AddPragmaHandler(MSInitSeg.get());
+ MSDataSeg.reset(new PragmaMSPragma("data_seg"));
+ PP.AddPragmaHandler(MSDataSeg.get());
+ MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
+ PP.AddPragmaHandler(MSBSSSeg.get());
+ MSConstSeg.reset(new PragmaMSPragma("const_seg"));
+ PP.AddPragmaHandler(MSConstSeg.get());
+ MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
+ PP.AddPragmaHandler(MSCodeSeg.get());
+ MSSection.reset(new PragmaMSPragma("section"));
+ PP.AddPragmaHandler(MSSection.get());
+ }
+
+ OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
+ PP.AddPragmaHandler("clang", OptimizeHandler.get());
+
+ LoopHintHandler.reset(new PragmaLoopHintHandler());
+ PP.AddPragmaHandler("clang", LoopHintHandler.get());
+
+ UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll"));
+ PP.AddPragmaHandler(UnrollHintHandler.get());
+}
+
+void Parser::resetPragmaHandlers() {
+ // Remove the pragma handlers we installed.
+ PP.RemovePragmaHandler(AlignHandler.get());
+ AlignHandler.reset();
+ PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
+ GCCVisibilityHandler.reset();
+ PP.RemovePragmaHandler(OptionsHandler.get());
+ OptionsHandler.reset();
+ PP.RemovePragmaHandler(PackHandler.get());
+ PackHandler.reset();
+ PP.RemovePragmaHandler(MSStructHandler.get());
+ MSStructHandler.reset();
+ PP.RemovePragmaHandler(UnusedHandler.get());
+ UnusedHandler.reset();
+ PP.RemovePragmaHandler(WeakHandler.get());
+ WeakHandler.reset();
+ PP.RemovePragmaHandler(RedefineExtnameHandler.get());
+ RedefineExtnameHandler.reset();
+
+ if (getLangOpts().OpenCL) {
+ PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
+ OpenCLExtensionHandler.reset();
+ PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
+ }
+ PP.RemovePragmaHandler(OpenMPHandler.get());
+ OpenMPHandler.reset();
+
+ if (getLangOpts().MicrosoftExt) {
+ PP.RemovePragmaHandler(MSCommentHandler.get());
+ MSCommentHandler.reset();
+ PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
+ MSDetectMismatchHandler.reset();
+ PP.RemovePragmaHandler(MSPointersToMembers.get());
+ MSPointersToMembers.reset();
+ PP.RemovePragmaHandler(MSVtorDisp.get());
+ MSVtorDisp.reset();
+ PP.RemovePragmaHandler(MSInitSeg.get());
+ MSInitSeg.reset();
+ PP.RemovePragmaHandler(MSDataSeg.get());
+ MSDataSeg.reset();
+ PP.RemovePragmaHandler(MSBSSSeg.get());
+ MSBSSSeg.reset();
+ PP.RemovePragmaHandler(MSConstSeg.get());
+ MSConstSeg.reset();
+ PP.RemovePragmaHandler(MSCodeSeg.get());
+ MSCodeSeg.reset();
+ PP.RemovePragmaHandler(MSSection.get());
+ MSSection.reset();
+ }
+
+ PP.RemovePragmaHandler("STDC", FPContractHandler.get());
+ FPContractHandler.reset();
+
+ PP.RemovePragmaHandler("clang", OptimizeHandler.get());
+ OptimizeHandler.reset();
+
+ PP.RemovePragmaHandler("clang", LoopHintHandler.get());
+ LoopHintHandler.reset();
+
+ PP.RemovePragmaHandler(UnrollHintHandler.get());
+ UnrollHintHandler.reset();
+}
+
/// \brief Handle the annotation token produced for #pragma unused(...)
///
/// Each annot_pragma_unused is followed by the argument token so e.g.
@@ -130,7 +404,7 @@ StmtResult Parser::HandlePragmaCaptured()
ConsumeToken();
if (Tok.isNot(tok::l_brace)) {
- PP.Diag(Tok, diag::err_expected_lbrace);
+ PP.Diag(Tok, diag::err_expected) << tok::l_brace;
return StmtError();
}
@@ -180,7 +454,307 @@ void Parser::HandlePragmaOpenCLExtension() {
}
}
+void Parser::HandlePragmaMSPointersToMembers() {
+ assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
+ LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
+ static_cast<LangOptions::PragmaMSPointersToMembersKind>(
+ reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
+ SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
+ Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
+}
+
+void Parser::HandlePragmaMSVtorDisp() {
+ assert(Tok.is(tok::annot_pragma_ms_vtordisp));
+ uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
+ Sema::PragmaVtorDispKind Kind =
+ static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF);
+ MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
+ SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
+ Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode);
+}
+void Parser::HandlePragmaMSPragma() {
+ assert(Tok.is(tok::annot_pragma_ms_pragma));
+ // Grab the tokens out of the annotation and enter them into the stream.
+ auto TheTokens = (std::pair<Token*, size_t> *)Tok.getAnnotationValue();
+ PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true);
+ SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
+ assert(Tok.isAnyIdentifier());
+ StringRef PragmaName = Tok.getIdentifierInfo()->getName();
+ PP.Lex(Tok); // pragma kind
+
+ // Figure out which #pragma we're dealing with. The switch has no default
+ // because lex shouldn't emit the annotation token for unrecognized pragmas.
+ typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
+ PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
+ .Case("data_seg", &Parser::HandlePragmaMSSegment)
+ .Case("bss_seg", &Parser::HandlePragmaMSSegment)
+ .Case("const_seg", &Parser::HandlePragmaMSSegment)
+ .Case("code_seg", &Parser::HandlePragmaMSSegment)
+ .Case("section", &Parser::HandlePragmaMSSection)
+ .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
+
+ if (!(this->*Handler)(PragmaName, PragmaLocation)) {
+ // Pragma handling failed, and has been diagnosed. Slurp up the tokens
+ // until eof (really end of line) to prevent follow-on errors.
+ while (Tok.isNot(tok::eof))
+ PP.Lex(Tok);
+ PP.Lex(Tok);
+ }
+}
+
+bool Parser::HandlePragmaMSSection(StringRef PragmaName,
+ SourceLocation PragmaLocation) {
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
+ return false;
+ }
+ PP.Lex(Tok); // (
+ // Parsing code for pragma section
+ if (Tok.isNot(tok::string_literal)) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
+ << PragmaName;
+ return false;
+ }
+ ExprResult StringResult = ParseStringLiteralExpression();
+ if (StringResult.isInvalid())
+ return false; // Already diagnosed.
+ StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
+ if (SegmentName->getCharByteWidth() != 1) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
+ << PragmaName;
+ return false;
+ }
+ int SectionFlags = 0;
+ while (Tok.is(tok::comma)) {
+ PP.Lex(Tok); // ,
+ if (!Tok.isAnyIdentifier()) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
+ << PragmaName;
+ return false;
+ }
+ Sema::PragmaSectionFlag Flag =
+ llvm::StringSwitch<Sema::PragmaSectionFlag>(
+ Tok.getIdentifierInfo()->getName())
+ .Case("read", Sema::PSF_Read)
+ .Case("write", Sema::PSF_Write)
+ .Case("execute", Sema::PSF_Execute)
+ .Case("shared", Sema::PSF_Invalid)
+ .Case("nopage", Sema::PSF_Invalid)
+ .Case("nocache", Sema::PSF_Invalid)
+ .Case("discard", Sema::PSF_Invalid)
+ .Case("remove", Sema::PSF_Invalid)
+ .Default(Sema::PSF_None);
+ if (Flag == Sema::PSF_None || Flag == Sema::PSF_Invalid) {
+ PP.Diag(PragmaLocation, Flag == Sema::PSF_None
+ ? diag::warn_pragma_invalid_specific_action
+ : diag::warn_pragma_unsupported_action)
+ << PragmaName << Tok.getIdentifierInfo()->getName();
+ return false;
+ }
+ SectionFlags |= Flag;
+ PP.Lex(Tok); // Identifier
+ }
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
+ return false;
+ }
+ PP.Lex(Tok); // )
+ if (Tok.isNot(tok::eof)) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
+ << PragmaName;
+ return false;
+ }
+ PP.Lex(Tok); // eof
+ Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
+ return true;
+}
+
+bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
+ SourceLocation PragmaLocation) {
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
+ return false;
+ }
+ PP.Lex(Tok); // (
+ Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
+ StringRef SlotLabel;
+ if (Tok.isAnyIdentifier()) {
+ StringRef PushPop = Tok.getIdentifierInfo()->getName();
+ if (PushPop == "push")
+ Action = Sema::PSK_Push;
+ else if (PushPop == "pop")
+ Action = Sema::PSK_Pop;
+ else {
+ PP.Diag(PragmaLocation,
+ diag::warn_pragma_expected_section_push_pop_or_name)
+ << PragmaName;
+ return false;
+ }
+ if (Action != Sema::PSK_Reset) {
+ PP.Lex(Tok); // push | pop
+ if (Tok.is(tok::comma)) {
+ PP.Lex(Tok); // ,
+ // If we've got a comma, we either need a label or a string.
+ if (Tok.isAnyIdentifier()) {
+ SlotLabel = Tok.getIdentifierInfo()->getName();
+ PP.Lex(Tok); // identifier
+ if (Tok.is(tok::comma))
+ PP.Lex(Tok);
+ else if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
+ << PragmaName;
+ return false;
+ }
+ }
+ } else if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
+ return false;
+ }
+ }
+ }
+ // Grab the string literal for our section name.
+ StringLiteral *SegmentName = nullptr;
+ if (Tok.isNot(tok::r_paren)) {
+ if (Tok.isNot(tok::string_literal)) {
+ unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
+ diag::warn_pragma_expected_section_name :
+ diag::warn_pragma_expected_section_label_or_name :
+ diag::warn_pragma_expected_section_push_pop_or_name;
+ PP.Diag(PragmaLocation, DiagID) << PragmaName;
+ return false;
+ }
+ ExprResult StringResult = ParseStringLiteralExpression();
+ if (StringResult.isInvalid())
+ return false; // Already diagnosed.
+ SegmentName = cast<StringLiteral>(StringResult.get());
+ if (SegmentName->getCharByteWidth() != 1) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
+ << PragmaName;
+ return false;
+ }
+ // Setting section "" has no effect
+ if (SegmentName->getLength())
+ Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
+ }
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
+ return false;
+ }
+ PP.Lex(Tok); // )
+ if (Tok.isNot(tok::eof)) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
+ << PragmaName;
+ return false;
+ }
+ PP.Lex(Tok); // eof
+ Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
+ SegmentName, PragmaName);
+ return true;
+}
+
+// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
+bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
+ SourceLocation PragmaLocation) {
+ if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
+ return false;
+ }
+
+ if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
+ PragmaName))
+ return false;
+
+ // Parse either the known section names or the string section name.
+ StringLiteral *SegmentName = nullptr;
+ if (Tok.isAnyIdentifier()) {
+ auto *II = Tok.getIdentifierInfo();
+ StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
+ .Case("compiler", "\".CRT$XCC\"")
+ .Case("lib", "\".CRT$XCL\"")
+ .Case("user", "\".CRT$XCU\"")
+ .Default("");
+
+ if (!Section.empty()) {
+ // Pretend the user wrote the appropriate string literal here.
+ Token Toks[1];
+ Toks[0].startToken();
+ Toks[0].setKind(tok::string_literal);
+ Toks[0].setLocation(Tok.getLocation());
+ Toks[0].setLiteralData(Section.data());
+ Toks[0].setLength(Section.size());
+ SegmentName =
+ cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
+ PP.Lex(Tok);
+ }
+ } else if (Tok.is(tok::string_literal)) {
+ ExprResult StringResult = ParseStringLiteralExpression();
+ if (StringResult.isInvalid())
+ return false;
+ SegmentName = cast<StringLiteral>(StringResult.get());
+ if (SegmentName->getCharByteWidth() != 1) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
+ << PragmaName;
+ return false;
+ }
+ // FIXME: Add support for the '[, func-name]' part of the pragma.
+ }
+
+ if (!SegmentName) {
+ PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
+ return false;
+ }
+
+ if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
+ PragmaName) ||
+ ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
+ PragmaName))
+ return false;
+
+ Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
+ return true;
+}
+
+struct PragmaLoopHintInfo {
+ Token PragmaName;
+ Token Option;
+ Token Value;
+ bool HasValue;
+};
+
+LoopHint Parser::HandlePragmaLoopHint() {
+ assert(Tok.is(tok::annot_pragma_loop_hint));
+ PragmaLoopHintInfo *Info =
+ static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
+
+ LoopHint Hint;
+ Hint.PragmaNameLoc =
+ IdentifierLoc::create(Actions.Context, Info->PragmaName.getLocation(),
+ Info->PragmaName.getIdentifierInfo());
+ Hint.OptionLoc =
+ IdentifierLoc::create(Actions.Context, Info->Option.getLocation(),
+ Info->Option.getIdentifierInfo());
+ if (Info->HasValue) {
+ Hint.Range =
+ SourceRange(Info->Option.getLocation(), Info->Value.getLocation());
+ Hint.ValueLoc =
+ IdentifierLoc::create(Actions.Context, Info->Value.getLocation(),
+ Info->Value.getIdentifierInfo());
+
+ // FIXME: We should allow non-type template parameters for the loop hint
+ // value. See bug report #19610
+ if (Info->Value.is(tok::numeric_constant))
+ Hint.ValueExpr = Actions.ActOnNumericConstant(Info->Value).get();
+ else
+ Hint.ValueExpr = nullptr;
+ } else {
+ Hint.Range = SourceRange(Info->PragmaName.getLocation());
+ Hint.ValueLoc = nullptr;
+ Hint.ValueExpr = nullptr;
+ }
+
+ return Hint;
+}
// #pragma GCC visibility comes in two variants:
// 'push' '(' [visibility] ')'
@@ -197,7 +771,7 @@ void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
const IdentifierInfo *VisType;
if (PushPop && PushPop->isStr("pop")) {
- VisType = 0;
+ VisType = nullptr;
} else if (PushPop && PushPop->isStr("push")) {
PP.LexUnexpandedToken(Tok);
if (Tok.isNot(tok::l_paren)) {
@@ -257,7 +831,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP,
}
Sema::PragmaPackKind Kind = Sema::PPK_Default;
- IdentifierInfo *Name = 0;
+ IdentifierInfo *Name = nullptr;
Token Alignment;
Alignment.startToken();
SourceLocation LParenLoc = Tok.getLocation();
@@ -283,7 +857,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP,
} else if (II->isStr("pop")) {
Kind = Sema::PPK_Pop;
} else {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
return;
}
PP.Lex(Tok);
@@ -530,7 +1104,7 @@ void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
}
// Illegal token!
- PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
return;
}
@@ -760,13 +1334,11 @@ void
PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &FirstTok) {
- if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored,
- FirstTok.getLocation()) !=
- DiagnosticsEngine::Ignored) {
+ if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
+ FirstTok.getLocation())) {
PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
- PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored,
- diag::MAP_IGNORE,
- SourceLocation());
+ PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
+ diag::Severity::Ignored, SourceLocation());
}
PP.DiscardUntilEndOfDirective();
}
@@ -799,6 +1371,220 @@ PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
/*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
}
+/// \brief Handle '#pragma pointers_to_members'
+// The grammar for this pragma is as follows:
+//
+// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
+//
+// #pragma pointers_to_members '(' 'best_case' ')'
+// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
+// #pragma pointers_to_members '(' inheritance-model ')'
+void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ SourceLocation PointersToMembersLoc = Tok.getLocation();
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
+ << "pointers_to_members";
+ return;
+ }
+ PP.Lex(Tok);
+ const IdentifierInfo *Arg = Tok.getIdentifierInfo();
+ if (!Arg) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
+ << "pointers_to_members";
+ return;
+ }
+ PP.Lex(Tok);
+
+ LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
+ if (Arg->isStr("best_case")) {
+ RepresentationMethod = LangOptions::PPTMK_BestCase;
+ } else {
+ if (Arg->isStr("full_generality")) {
+ if (Tok.is(tok::comma)) {
+ PP.Lex(Tok);
+
+ Arg = Tok.getIdentifierInfo();
+ if (!Arg) {
+ PP.Diag(Tok.getLocation(),
+ diag::err_pragma_pointers_to_members_unknown_kind)
+ << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
+ return;
+ }
+ PP.Lex(Tok);
+ } else if (Tok.is(tok::r_paren)) {
+ // #pragma pointers_to_members(full_generality) implicitly specifies
+ // virtual_inheritance.
+ Arg = nullptr;
+ RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
+ } else {
+ PP.Diag(Tok.getLocation(), diag::err_expected_punc)
+ << "full_generality";
+ return;
+ }
+ }
+
+ if (Arg) {
+ if (Arg->isStr("single_inheritance")) {
+ RepresentationMethod =
+ LangOptions::PPTMK_FullGeneralitySingleInheritance;
+ } else if (Arg->isStr("multiple_inheritance")) {
+ RepresentationMethod =
+ LangOptions::PPTMK_FullGeneralityMultipleInheritance;
+ } else if (Arg->isStr("virtual_inheritance")) {
+ RepresentationMethod =
+ LangOptions::PPTMK_FullGeneralityVirtualInheritance;
+ } else {
+ PP.Diag(Tok.getLocation(),
+ diag::err_pragma_pointers_to_members_unknown_kind)
+ << Arg << /*HasPointerDeclaration*/ 1;
+ return;
+ }
+ }
+ }
+
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
+ << (Arg ? Arg->getName() : "full_generality");
+ return;
+ }
+
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "pointers_to_members";
+ return;
+ }
+
+ Token AnnotTok;
+ AnnotTok.startToken();
+ AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
+ AnnotTok.setLocation(PointersToMembersLoc);
+ AnnotTok.setAnnotationValue(
+ reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
+ PP.EnterToken(AnnotTok);
+}
+
+/// \brief Handle '#pragma vtordisp'
+// The grammar for this pragma is as follows:
+//
+// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
+//
+// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
+// #pragma vtordisp '(' 'pop' ')'
+// #pragma vtordisp '(' ')'
+void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ SourceLocation VtorDispLoc = Tok.getLocation();
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
+ return;
+ }
+ PP.Lex(Tok);
+
+ Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set;
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (II) {
+ if (II->isStr("push")) {
+ // #pragma vtordisp(push, mode)
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::comma)) {
+ PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
+ return;
+ }
+ PP.Lex(Tok);
+ Kind = Sema::PVDK_Push;
+ // not push, could be on/off
+ } else if (II->isStr("pop")) {
+ // #pragma vtordisp(pop)
+ PP.Lex(Tok);
+ Kind = Sema::PVDK_Pop;
+ }
+ // not push or pop, could be on/off
+ } else {
+ if (Tok.is(tok::r_paren)) {
+ // #pragma vtordisp()
+ Kind = Sema::PVDK_Reset;
+ }
+ }
+
+
+ uint64_t Value = 0;
+ if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) {
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (II && II->isStr("off")) {
+ PP.Lex(Tok);
+ Value = 0;
+ } else if (II && II->isStr("on")) {
+ PP.Lex(Tok);
+ Value = 1;
+ } else if (Tok.is(tok::numeric_constant) &&
+ PP.parseSimpleIntegerLiteral(Tok, Value)) {
+ if (Value > 2) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
+ << 0 << 2 << "vtordisp";
+ return;
+ }
+ } else {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
+ << "vtordisp";
+ return;
+ }
+ }
+
+ // Finish the pragma: ')' $
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
+ return;
+ }
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "vtordisp";
+ return;
+ }
+
+ // Enter the annotation.
+ Token AnnotTok;
+ AnnotTok.startToken();
+ AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
+ AnnotTok.setLocation(VtorDispLoc);
+ AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
+ static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF))));
+ PP.EnterToken(AnnotTok);
+}
+
+/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
+/// an annotation token.
+void PragmaMSPragma::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ Token EoF, AnnotTok;
+ EoF.startToken();
+ EoF.setKind(tok::eof);
+ AnnotTok.startToken();
+ AnnotTok.setKind(tok::annot_pragma_ms_pragma);
+ AnnotTok.setLocation(Tok.getLocation());
+ SmallVector<Token, 8> TokenVector;
+ // Suck up all of the tokens before the eod.
+ for (; Tok.isNot(tok::eod); PP.Lex(Tok))
+ TokenVector.push_back(Tok);
+ // 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
+ // delete it later.
+ Token *TokenArray = new Token[TokenVector.size()];
+ std::copy(TokenVector.begin(), TokenVector.end(), TokenArray);
+ auto Value = new (PP.getPreprocessorAllocator())
+ std::pair<Token*, size_t>(std::make_pair(TokenArray, TokenVector.size()));
+ AnnotTok.setAnnotationValue(Value);
+ PP.EnterToken(AnnotTok);
+}
+
/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
///
/// The syntax is:
@@ -815,7 +1601,7 @@ void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
SourceLocation CommentLoc = Tok.getLocation();
PP.Lex(Tok);
if (Tok.isNot(tok::l_paren)) {
- PP.Diag(CommentLoc, diag::err_expected_lparen);
+ PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
return;
}
@@ -838,7 +1624,7 @@ void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
return;
if (Tok.isNot(tok::r_paren)) {
- PP.Diag(Tok.getLocation(), diag::err_expected_rparen);
+ PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
return;
}
PP.Lex(Tok); // Eat the r_paren.
@@ -929,3 +1715,251 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
Actions.ActOnPragmaMSComment(Kind, ArgumentString);
}
+
+// #pragma clang optimize off
+// #pragma clang optimize on
+void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &FirstToken) {
+ Token Tok;
+ PP.Lex(Tok);
+ if (Tok.is(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
+ << "clang optimize"
+ << "'on' or 'off'";
+ return;
+ }
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
+ << PP.getSpelling(Tok);
+ return;
+ }
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ // The only accepted values are 'on' or 'off'.
+ bool IsOn = false;
+ if (II->isStr("on")) {
+ IsOn = true;
+ } else if (!II->isStr("off")) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
+ << PP.getSpelling(Tok);
+ return;
+ }
+ PP.Lex(Tok);
+
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
+ << PP.getSpelling(Tok);
+ return;
+ }
+
+ Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
+}
+
+/// \brief Parses loop or unroll pragma hint value and fills in Info.
+static bool ParseLoopHintValue(Preprocessor &PP, Token Tok, Token &PragmaName,
+ Token &Option, bool &ValueInParens,
+ PragmaLoopHintInfo &Info) {
+ ValueInParens = Tok.is(tok::l_paren);
+ if (ValueInParens) {
+ PP.Lex(Tok);
+ if (Tok.is(tok::r_paren)) {
+ // Nothing between the parentheses.
+ std::string PragmaString;
+ if (PragmaName.getIdentifierInfo()->getName() == "loop") {
+ PragmaString = "clang loop ";
+ PragmaString += Option.getIdentifierInfo()->getName();
+ } else {
+ assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
+ "Unexpected pragma name");
+ PragmaString = "unroll";
+ }
+ PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
+ << PragmaString << "a positive integer value";
+ return true;
+ }
+ }
+
+ // FIXME: Value should be stored and parsed as a constant expression.
+ Token Value = Tok;
+
+ if (ValueInParens) {
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
+ return true;
+ }
+ }
+
+ Info.PragmaName = PragmaName;
+ Info.Option = Option;
+ Info.Value = Value;
+ Info.HasValue = true;
+ return false;
+}
+
+/// \brief Handle the \#pragma clang loop directive.
+/// #pragma clang 'loop' loop-hints
+///
+/// loop-hints:
+/// loop-hint loop-hints[opt]
+///
+/// loop-hint:
+/// 'vectorize' '(' loop-hint-keyword ')'
+/// 'interleave' '(' loop-hint-keyword ')'
+/// 'unroll' '(' loop-hint-keyword ')'
+/// 'vectorize_width' '(' loop-hint-value ')'
+/// 'interleave_count' '(' loop-hint-value ')'
+/// 'unroll_count' '(' loop-hint-value ')'
+///
+/// loop-hint-keyword:
+/// 'enable'
+/// 'disable'
+///
+/// loop-hint-value:
+/// constant-expression
+///
+/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
+/// try vectorizing the instructions of the loop it precedes. Specifying
+/// interleave(enable) or interleave_count(_value_) instructs llvm to try
+/// interleaving multiple iterations of the loop it precedes. The width of the
+/// vector instructions is specified by vectorize_width() and the number of
+/// interleaved loop iterations is specified by interleave_count(). Specifying a
+/// value of 1 effectively disables vectorization/interleaving, even if it is
+/// possible and profitable, and 0 is invalid. The loop vectorizer currently
+/// only works on inner loops.
+///
+/// The unroll and unroll_count directives control the concatenation
+/// unroller. Specifying unroll(enable) instructs llvm to try to
+/// unroll the loop completely, and unroll(disable) disables unrolling
+/// for the loop. Specifying unroll_count(_value_) instructs llvm to
+/// try to unroll the loop the number of times indicated by the value.
+/// If unroll(enable) and unroll_count are both specified only
+/// unroll_count takes effect.
+void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ // Incoming token is "loop" from "#pragma clang loop".
+ Token PragmaName = Tok;
+ SmallVector<Token, 1> TokenList;
+
+ // Lex the optimization option and verify it is an identifier.
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
+ << /*MissingOption=*/true << "";
+ return;
+ }
+
+ while (Tok.is(tok::identifier)) {
+ Token Option = Tok;
+ IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
+
+ bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
+ .Case("vectorize", true)
+ .Case("interleave", true)
+ .Case("unroll", true)
+ .Case("vectorize_width", true)
+ .Case("interleave_count", true)
+ .Case("unroll_count", true)
+ .Default(false);
+ if (!OptionValid) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
+ << /*MissingOption=*/false << OptionInfo;
+ return;
+ }
+
+ auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
+ PP.Lex(Tok);
+ bool ValueInParens;
+ if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
+ return;
+
+ if (!ValueInParens) {
+ PP.Diag(Info->Value.getLocation(), diag::err_expected) << tok::l_paren;
+ return;
+ }
+
+ // Generate the loop hint token.
+ Token LoopHintTok;
+ LoopHintTok.startToken();
+ LoopHintTok.setKind(tok::annot_pragma_loop_hint);
+ LoopHintTok.setLocation(PragmaName.getLocation());
+ LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
+ TokenList.push_back(LoopHintTok);
+
+ // Get next optimization option.
+ PP.Lex(Tok);
+ }
+
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "clang loop";
+ return;
+ }
+
+ Token *TokenArray = new Token[TokenList.size()];
+ std::copy(TokenList.begin(), TokenList.end(), TokenArray);
+
+ PP.EnterTokenStream(TokenArray, TokenList.size(),
+ /*DisableMacroExpansion=*/false,
+ /*OwnsTokens=*/true);
+}
+
+/// \brief Handle the loop unroll optimization pragmas.
+/// #pragma unroll
+/// #pragma unroll unroll-hint-value
+/// #pragma unroll '(' unroll-hint-value ')'
+///
+/// unroll-hint-value:
+/// constant-expression
+///
+/// Loop unrolling hints are specified with '#pragma unroll'. '#pragma unroll'
+/// can take a numeric argument optionally contained in parentheses. With no
+/// argument the directive instructs llvm to try to unroll the loop
+/// completely. A positive integer argument can be specified to indicate the
+/// number of times the loop should be unrolled. To maximize compatibility with
+/// other compilers the unroll count argument can be specified with or without
+/// parentheses.
+void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ // Incoming token is "unroll" of "#pragma unroll".
+ Token PragmaName = Tok;
+ PP.Lex(Tok);
+ auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
+ if (Tok.is(tok::eod)) {
+ // Unroll pragma without an argument.
+ Info->PragmaName = PragmaName;
+ Info->Option = PragmaName;
+ Info->HasValue = false;
+ } else {
+ // Unroll pragma with an argument: "#pragma unroll N" or
+ // "#pragma unroll(N)".
+ bool ValueInParens;
+ if (ParseLoopHintValue(PP, Tok, PragmaName, PragmaName, ValueInParens,
+ *Info))
+ return;
+
+ // In CUDA, the argument to '#pragma unroll' should not be contained in
+ // parentheses.
+ if (PP.getLangOpts().CUDA && ValueInParens)
+ PP.Diag(Info->Value.getLocation(),
+ diag::warn_pragma_unroll_cuda_value_in_parens);
+
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "unroll";
+ return;
+ }
+ }
+
+ // Generate the hint token.
+ Token *TokenArray = new Token[1];
+ TokenArray[0].startToken();
+ TokenArray[0].setKind(tok::annot_pragma_loop_hint);
+ TokenArray[0].setLocation(PragmaName.getLocation());
+ TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
+ PP.EnterTokenStream(TokenArray, 1, /*DisableMacroExpansion=*/false,
+ /*OwnsTokens=*/true);
+}
diff --git a/lib/Parse/ParsePragma.h b/lib/Parse/ParsePragma.h
deleted file mode 100644
index b41450f4eadf..000000000000
--- a/lib/Parse/ParsePragma.h
+++ /dev/null
@@ -1,139 +0,0 @@
-//===---- ParserPragmas.h - Language specific pragmas -----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines #pragma handlers for language specific pragmas.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_PARSE_PARSEPRAGMA_H
-#define LLVM_CLANG_PARSE_PARSEPRAGMA_H
-
-#include "clang/Lex/Pragma.h"
-
-namespace clang {
- class Sema;
- class Parser;
-
-class PragmaAlignHandler : public PragmaHandler {
-public:
- explicit PragmaAlignHandler() : PragmaHandler("align") {}
-
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaGCCVisibilityHandler : public PragmaHandler {
-public:
- explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
-
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaOptionsHandler : public PragmaHandler {
-public:
- explicit PragmaOptionsHandler() : PragmaHandler("options") {}
-
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaPackHandler : public PragmaHandler {
-public:
- explicit PragmaPackHandler() : PragmaHandler("pack") {}
-
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaMSStructHandler : public PragmaHandler {
-public:
- explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
-
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaUnusedHandler : public PragmaHandler {
-public:
- PragmaUnusedHandler() : PragmaHandler("unused") {}
-
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaWeakHandler : public PragmaHandler {
-public:
- explicit PragmaWeakHandler() : PragmaHandler("weak") {}
-
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaRedefineExtnameHandler : public PragmaHandler {
-public:
- explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
-
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaOpenCLExtensionHandler : public PragmaHandler {
-public:
- PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-
-class PragmaFPContractHandler : public PragmaHandler {
-public:
- PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaNoOpenMPHandler : public PragmaHandler {
-public:
- PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaOpenMPHandler : public PragmaHandler {
-public:
- PragmaOpenMPHandler() : PragmaHandler("omp") { }
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-/// PragmaCommentHandler - "\#pragma comment ...".
-class PragmaCommentHandler : public PragmaHandler {
-public:
- PragmaCommentHandler(Sema &Actions)
- : PragmaHandler("comment"), Actions(Actions) {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-private:
- Sema &Actions;
-};
-
-class PragmaDetectMismatchHandler : public PragmaHandler {
-public:
- PragmaDetectMismatchHandler(Sema &Actions)
- : PragmaHandler("detect_mismatch"), Actions(Actions) {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-private:
- Sema &Actions;
-};
-
-} // end namespace clang
-
-#endif
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index d1f2138db48f..ec0ca6b1fdd6 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -15,25 +15,14 @@
#include "clang/Parse/Parser.h"
#include "RAIIObjectsForParser.h"
#include "clang/AST/ASTContext.h"
+#include "clang/Basic/Attributes.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/PrettyStackTrace.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/LoopHint.h"
#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/TypoCorrection.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCParser/MCAsmParser.h"
-#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/MC/MCTargetAsmParser.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/TargetRegistry.h"
-#include "llvm/Support/TargetSelect.h"
#include "llvm/ADT/SmallString.h"
using namespace clang;
@@ -112,7 +101,7 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement,
ParenBraceBracketBalancer BalancerRAIIObj(*this);
ParsedAttributesWithRange Attrs(AttrFactory);
- MaybeParseCXX11Attributes(Attrs, 0, /*MightBeObjCMessageSend*/ true);
+ MaybeParseCXX11Attributes(Attrs, nullptr, /*MightBeObjCMessageSend*/ true);
StmtResult Res = ParseStatementOrDeclarationAfterAttributes(Stmts,
OnlyStatement, TrailingElseLoc, Attrs);
@@ -142,7 +131,7 @@ public:
WantCXXNamedCasts = false;
}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
if (FieldDecl *FD = candidate.getCorrectionDeclAs<FieldDecl>())
return !candidate.getCorrectionSpecifier() || isa<ObjCIvarDecl>(FD);
if (NextToken.is(tok::equal))
@@ -162,7 +151,7 @@ StmtResult
Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts,
bool OnlyStatement, SourceLocation *TrailingElseLoc,
ParsedAttributesWithRange &Attrs) {
- const char *SemiError = 0;
+ const char *SemiError = nullptr;
StmtResult Res;
// Cases in this switch statement should fall through if the parser expects
@@ -284,6 +273,14 @@ Retry:
break;
}
+ case tok::kw___if_exists:
+ case tok::kw___if_not_exists:
+ ProhibitAttributes(Attrs);
+ ParseMicrosoftIfExistsStatement(Stmts);
+ // An __if_exists block is like a compound statement, but it doesn't create
+ // a new scope.
+ return StmtEmpty();
+
case tok::kw_try: // C++ 15: try-block
return ParseCXXTryBlock();
@@ -291,6 +288,11 @@ Retry:
ProhibitAttributes(Attrs); // TODO: is it correct?
return ParseSEHTryBlock();
+ case tok::kw___leave:
+ Res = ParseSEHLeaveStatement();
+ SemiError = "__leave";
+ break;
+
case tok::annot_pragma_vis:
ProhibitAttributes(Attrs);
HandlePragmaVisibility();
@@ -343,14 +345,25 @@ Retry:
case tok::annot_pragma_openmp:
ProhibitAttributes(Attrs);
- return ParseOpenMPDeclarativeOrExecutableDirective();
+ return ParseOpenMPDeclarativeOrExecutableDirective(!OnlyStatement);
+
+ case tok::annot_pragma_ms_pointers_to_members:
+ ProhibitAttributes(Attrs);
+ HandlePragmaMSPointersToMembers();
+ return StmtEmpty();
+ case tok::annot_pragma_ms_pragma:
+ ProhibitAttributes(Attrs);
+ HandlePragmaMSPragma();
+ return StmtEmpty();
+
+ case tok::annot_pragma_loop_hint:
+ ProhibitAttributes(Attrs);
+ return ParsePragmaLoopHint(Stmts, OnlyStatement, TrailingElseLoc, Attrs);
}
// If we reached this code, the statement must end in a semicolon.
- if (Tok.is(tok::semi)) {
- ConsumeToken();
- } else if (!Res.isInvalid()) {
+ if (!TryConsumeToken(tok::semi) && !Res.isInvalid()) {
// If the result was valid, then we do want to diagnose this. Use
// ExpectAndConsume to emit the diagnostic, even though we know it won't
// succeed.
@@ -411,10 +424,27 @@ StmtResult Parser::ParseSEHTryBlock() {
/// seh-finally-block
///
StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) {
- if(Tok.isNot(tok::l_brace))
- return StmtError(Diag(Tok,diag::err_expected_lbrace));
+ if (Tok.isNot(tok::l_brace))
+ return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
+
+ int SEHTryIndex, SEHTryParentIndex;
+ StmtResult TryBlock;
+ {
+ assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
+
+ // Enter a scope to hold everything within the compound stmt. Compound
+ // statements can always hold declarations.
+ ParseScope CompoundScope(this, Scope::DeclScope | Scope::SEHTryScope);
+ SEHTryIndex = getCurScope()->getSEHTryIndex();
+ SEHTryParentIndex = getCurScope()->getSEHTryParentIndex();
+
+ // Parse the statements in the body.
+ TryBlock = ParseCompoundStatementBody();
+ }
+
+ //StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false,
+ // Scope::DeclScope | Scope::SEHTryScope));
- StmtResult TryBlock(ParseCompoundStatement());
if(TryBlock.isInvalid())
return TryBlock;
@@ -435,8 +465,10 @@ StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) {
return Actions.ActOnSEHTryBlock(false /* IsCXXTry */,
TryLoc,
- TryBlock.take(),
- Handler.take());
+ TryBlock.get(),
+ Handler.get(),
+ SEHTryIndex,
+ SEHTryParentIndex);
}
/// ParseSEHExceptBlock - Handle __except
@@ -449,7 +481,7 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) {
raii2(Ident___exception_code, false),
raii3(Ident_GetExceptionCode, false);
- if(ExpectAndConsume(tok::l_paren,diag::err_expected_lparen))
+ if (ExpectAndConsume(tok::l_paren))
return StmtError();
ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope);
@@ -470,7 +502,7 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) {
if(FilterExpr.isInvalid())
return StmtError();
- if(ExpectAndConsume(tok::r_paren,diag::err_expected_rparen))
+ if (ExpectAndConsume(tok::r_paren))
return StmtError();
StmtResult Block(ParseCompoundStatement());
@@ -478,7 +510,7 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) {
if(Block.isInvalid())
return Block;
- return Actions.ActOnSEHExceptBlock(ExceptLoc, FilterExpr.take(), Block.take());
+ return Actions.ActOnSEHExceptBlock(ExceptLoc, FilterExpr.get(), Block.get());
}
/// ParseSEHFinallyBlock - Handle __finally
@@ -495,7 +527,17 @@ StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyBlock) {
if(Block.isInvalid())
return Block;
- return Actions.ActOnSEHFinallyBlock(FinallyBlock,Block.take());
+ return Actions.ActOnSEHFinallyBlock(FinallyBlock,Block.get());
+}
+
+/// Handle __leave
+///
+/// seh-leave-statement:
+/// '__leave' ';'
+///
+StmtResult Parser::ParseSEHLeaveStatement() {
+ SourceLocation LeaveLoc = ConsumeToken(); // eat the '__leave'.
+ return Actions.ActOnSEHLeaveStmt(LeaveLoc, getCurScope());
}
/// ParseLabeledStatement - We have an identifier and a ':' after it.
@@ -538,12 +580,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs) {
// can't handle GNU attributes), so only call it in the one case where
// GNU attributes are allowed.
SubStmt = ParseStatementOrDeclarationAfterAttributes(
- Stmts, /*OnlyStmts*/ true, 0, TempAttrs);
+ Stmts, /*OnlyStmts*/ true, nullptr, TempAttrs);
if (!TempAttrs.empty() && !SubStmt.isInvalid())
SubStmt = Actions.ProcessStmtAttributes(
SubStmt.get(), TempAttrs.getList(), TempAttrs.Range);
} else {
- Diag(Tok, diag::err_expected_semi_after) << "__attribute__";
+ Diag(Tok, diag::err_expected_after) << "__attribute__" << tok::semi;
}
}
@@ -595,13 +637,14 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
// DeepestParsedCaseStmt - This is the deepest statement we have parsed, which
// gets updated each time a new case is parsed, and whose body is unset so
// far. When parsing 'case 4', this is the 'case 3' node.
- Stmt *DeepestParsedCaseStmt = 0;
+ Stmt *DeepestParsedCaseStmt = nullptr;
// While we have case statements, eat and stack them.
SourceLocation ColonLoc;
do {
SourceLocation CaseLoc = MissingCase ? Expr.get()->getExprLoc() :
ConsumeToken(); // eat the 'case'.
+ ColonLoc = SourceLocation();
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteCase(getCurScope());
@@ -614,41 +657,52 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
/// expression.
ColonProtectionRAIIObject ColonProtection(*this);
- ExprResult LHS(MissingCase ? Expr : ParseConstantExpression());
- MissingCase = false;
- if (LHS.isInvalid()) {
- SkipUntil(tok::colon, StopAtSemi);
- return StmtError();
+ ExprResult LHS;
+ if (!MissingCase) {
+ LHS = ParseConstantExpression();
+ if (LHS.isInvalid()) {
+ // If constant-expression is parsed unsuccessfully, recover by skipping
+ // current case statement (moving to the colon that ends it).
+ if (SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch)) {
+ TryConsumeToken(tok::colon, ColonLoc);
+ continue;
+ }
+ return StmtError();
+ }
+ } else {
+ LHS = Expr;
+ MissingCase = false;
}
// GNU case range extension.
SourceLocation DotDotDotLoc;
ExprResult RHS;
- if (Tok.is(tok::ellipsis)) {
- Diag(Tok, diag::ext_gnu_case_range);
- DotDotDotLoc = ConsumeToken();
-
+ if (TryConsumeToken(tok::ellipsis, DotDotDotLoc)) {
+ Diag(DotDotDotLoc, diag::ext_gnu_case_range);
RHS = ParseConstantExpression();
if (RHS.isInvalid()) {
- SkipUntil(tok::colon, StopAtSemi);
+ if (SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch)) {
+ TryConsumeToken(tok::colon, ColonLoc);
+ continue;
+ }
return StmtError();
}
}
ColonProtection.restore();
- if (Tok.is(tok::colon)) {
- ColonLoc = ConsumeToken();
-
- // Treat "case blah;" as a typo for "case blah:".
- } else if (Tok.is(tok::semi)) {
- ColonLoc = ConsumeToken();
- Diag(ColonLoc, diag::err_expected_colon_after) << "'case'"
- << FixItHint::CreateReplacement(ColonLoc, ":");
+ if (TryConsumeToken(tok::colon, ColonLoc)) {
+ } else if (TryConsumeToken(tok::semi, ColonLoc) ||
+ TryConsumeToken(tok::coloncolon, ColonLoc)) {
+ // Treat "case blah;" or "case blah::" as a typo for "case blah:".
+ Diag(ColonLoc, diag::err_expected_after)
+ << "'case'" << tok::colon
+ << FixItHint::CreateReplacement(ColonLoc, ":");
} else {
SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
- Diag(ExpectedLoc, diag::err_expected_colon_after) << "'case'"
- << FixItHint::CreateInsertion(ExpectedLoc, ":");
+ Diag(ExpectedLoc, diag::err_expected_after)
+ << "'case'" << tok::colon
+ << FixItHint::CreateInsertion(ExpectedLoc, ":");
ColonLoc = ExpectedLoc;
}
@@ -676,8 +730,6 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
// Handle all case statements.
} while (Tok.is(tok::kw_case));
- assert(!TopLevelCase.isInvalid() && "Should have parsed at least one case!");
-
// If we found a non-case statement, start by parsing it.
StmtResult SubStmt;
@@ -685,19 +737,23 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
SubStmt = ParseStatement();
} else {
// Nicely diagnose the common error "switch (X) { case 4: }", which is
- // not valid.
- SourceLocation AfterColonLoc = PP.getLocForEndOfToken(ColonLoc);
- Diag(AfterColonLoc, diag::err_label_end_of_compound_statement)
- << FixItHint::CreateInsertion(AfterColonLoc, " ;");
- SubStmt = true;
+ // not valid. If ColonLoc doesn't point to a valid text location, there was
+ // another parsing error, so avoid producing extra diagnostics.
+ if (ColonLoc.isValid()) {
+ SourceLocation AfterColonLoc = PP.getLocForEndOfToken(ColonLoc);
+ Diag(AfterColonLoc, diag::err_label_end_of_compound_statement)
+ << FixItHint::CreateInsertion(AfterColonLoc, " ;");
+ }
+ SubStmt = StmtError();
}
- // Broken sub-stmt shouldn't prevent forming the case statement properly.
- if (SubStmt.isInvalid())
- SubStmt = Actions.ActOnNullStmt(SourceLocation());
-
// Install the body into the most deeply-nested case.
- Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get());
+ if (DeepestParsedCaseStmt) {
+ // Broken sub-stmt shouldn't prevent forming the case statement properly.
+ if (SubStmt.isInvalid())
+ SubStmt = Actions.ActOnNullStmt(SourceLocation());
+ Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get());
+ }
// Return the top level parsed statement tree.
return TopLevelCase;
@@ -713,18 +769,17 @@ StmtResult Parser::ParseDefaultStatement() {
SourceLocation DefaultLoc = ConsumeToken(); // eat the 'default'.
SourceLocation ColonLoc;
- if (Tok.is(tok::colon)) {
- ColonLoc = ConsumeToken();
-
- // Treat "default;" as a typo for "default:".
- } else if (Tok.is(tok::semi)) {
- ColonLoc = ConsumeToken();
- Diag(ColonLoc, diag::err_expected_colon_after) << "'default'"
- << FixItHint::CreateReplacement(ColonLoc, ":");
+ if (TryConsumeToken(tok::colon, ColonLoc)) {
+ } else if (TryConsumeToken(tok::semi, ColonLoc)) {
+ // Treat "default;" as a typo for "default:".
+ Diag(ColonLoc, diag::err_expected_after)
+ << "'default'" << tok::colon
+ << FixItHint::CreateReplacement(ColonLoc, ":");
} else {
SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
- Diag(ExpectedLoc, diag::err_expected_colon_after) << "'default'"
- << FixItHint::CreateInsertion(ExpectedLoc, ":");
+ Diag(ExpectedLoc, diag::err_expected_after)
+ << "'default'" << tok::colon
+ << FixItHint::CreateInsertion(ExpectedLoc, ":");
ColonLoc = ExpectedLoc;
}
@@ -767,7 +822,6 @@ StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
/// declaration
/// [GNU] '__extension__' declaration
/// statement
-/// [OMP] openmp-directive [TODO]
///
/// [GNU] label-declarations:
/// [GNU] label-declaration
@@ -776,10 +830,6 @@ StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
/// [GNU] label-declaration:
/// [GNU] '__label__' identifier-list ';'
///
-/// [OMP] openmp-directive: [TODO]
-/// [OMP] barrier-directive
-/// [OMP] flush-directive
-///
StmtResult Parser::ParseCompoundStatement(bool isStmtExpr,
unsigned ScopeFlags) {
assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
@@ -826,6 +876,12 @@ void Parser::ParseCompoundStatementLeadingPragmas() {
case tok::annot_pragma_fp_contract:
HandlePragmaFPContract();
break;
+ case tok::annot_pragma_ms_pointers_to_members:
+ HandlePragmaMSPointersToMembers();
+ break;
+ case tok::annot_pragma_ms_pragma:
+ HandlePragmaMSPragma();
+ break;
default:
checkForPragmas = false;
break;
@@ -867,7 +923,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
SmallVector<Decl *, 8> DeclsInGroup;
while (1) {
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
break;
}
@@ -875,9 +931,8 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
SourceLocation IdLoc = ConsumeToken();
DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, LabelLoc));
- if (!Tok.is(tok::comma))
+ if (!TryConsumeToken(tok::comma))
break;
- ConsumeToken();
}
DeclSpec DS(AttrFactory);
@@ -887,21 +942,15 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
ExpectAndConsumeSemi(diag::err_expected_semi_declaration);
if (R.isUsable())
- Stmts.push_back(R.release());
+ Stmts.push_back(R.get());
}
- while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
if (Tok.is(tok::annot_pragma_unused)) {
HandlePragmaUnused();
continue;
}
- if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) ||
- Tok.is(tok::kw___if_not_exists))) {
- ParseMicrosoftIfExistsStatement(Stmts);
- continue;
- }
-
StmtResult R;
if (Tok.isNot(tok::kw___extension__)) {
R = ParseStatementOrDeclaration(Stmts, false);
@@ -915,7 +964,8 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
ConsumeToken();
ParsedAttributesWithRange attrs(AttrFactory);
- MaybeParseCXX11Attributes(attrs, 0, /*MightBeObjCMessageSend*/ true);
+ MaybeParseCXX11Attributes(attrs, nullptr,
+ /*MightBeObjCMessageSend*/ true);
// If this is the start of a declaration, parse it as such.
if (isDeclarationStatement()) {
@@ -946,7 +996,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
}
if (R.isUsable())
- Stmts.push_back(R.release());
+ Stmts.push_back(R.get());
}
SourceLocation CloseLoc = Tok.getLocation();
@@ -983,7 +1033,7 @@ bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult,
ParseCXXCondition(ExprResult, DeclResult, Loc, ConvertToBoolean);
else {
ExprResult = ParseExpression();
- DeclResult = 0;
+ DeclResult = nullptr;
// If required, convert to a boolean value.
if (!ExprResult.isInvalid() && ConvertToBoolean)
@@ -1053,7 +1103,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
// Parse the condition.
ExprResult CondExp;
- Decl *CondVar = 0;
+ Decl *CondVar = nullptr;
if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true))
return StmtError();
@@ -1077,8 +1127,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
// would have to notify ParseStatement not to create a new scope. It's
// simpler to let it create a new scope.
//
- ParseScope InnerScope(this, Scope::DeclScope,
- C99orCXX && Tok.isNot(tok::l_brace));
+ ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
// Read the 'then' stmt.
SourceLocation ThenStmtLoc = Tok.getLocation();
@@ -1110,8 +1159,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
// The substatement in a selection-statement (each substatement, in the else
// form of the if statement) implicitly defines a local scope.
//
- ParseScope InnerScope(this, Scope::DeclScope,
- C99orCXX && Tok.isNot(tok::l_brace));
+ ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
ElseStmt = ParseStatement();
@@ -1131,8 +1179,8 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
// make turn the invalid one into a null stmt to avoid dropping the other
// part. If both are invalid, return error.
if ((ThenStmt.isInvalid() && ElseStmt.isInvalid()) ||
- (ThenStmt.isInvalid() && ElseStmt.get() == 0) ||
- (ThenStmt.get() == 0 && ElseStmt.isInvalid())) {
+ (ThenStmt.isInvalid() && ElseStmt.get() == nullptr) ||
+ (ThenStmt.get() == nullptr && ElseStmt.isInvalid())) {
// Both invalid, or one is invalid and other is non-present: return error.
return StmtError();
}
@@ -1175,14 +1223,14 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) {
// while, for, and switch statements are local to the if, while, for, or
// switch statement (including the controlled statement).
//
- unsigned ScopeFlags = Scope::BreakScope | Scope::SwitchScope;
+ unsigned ScopeFlags = Scope::SwitchScope;
if (C99orCXX)
ScopeFlags |= Scope::DeclScope | Scope::ControlScope;
ParseScope SwitchScope(this, ScopeFlags);
// Parse the condition.
ExprResult Cond;
- Decl *CondVar = 0;
+ Decl *CondVar = nullptr;
if (ParseParenExprOrCondition(Cond, CondVar, SwitchLoc, false))
return StmtError();
@@ -1213,8 +1261,13 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) {
// See comments in ParseIfStatement for why we create a scope for the
// condition and a new scope for substatement in C++.
//
- ParseScope InnerScope(this, Scope::DeclScope,
- C99orCXX && Tok.isNot(tok::l_brace));
+ getCurScope()->AddFlags(Scope::BreakScope);
+ ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
+
+ // We have incremented the mangling number for the SwitchScope and the
+ // InnerScope, which is one too many.
+ if (C99orCXX)
+ getCurScope()->decrementMSLocalManglingNumber();
// Read the body statement.
StmtResult Body(ParseStatement(TrailingElseLoc));
@@ -1223,15 +1276,6 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) {
InnerScope.Exit();
SwitchScope.Exit();
- if (Body.isInvalid()) {
- // FIXME: Remove the case statement list from the Switch statement.
-
- // Put the synthesized null statement on the same line as the end of switch
- // condition.
- SourceLocation SynthesizedNullStmtLocation = Cond.get()->getLocEnd();
- Body = Actions.ActOnNullStmt(SynthesizedNullStmtLocation);
- }
-
return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.get(), Body.get());
}
@@ -1274,13 +1318,13 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) {
// Parse the condition.
ExprResult Cond;
- Decl *CondVar = 0;
+ Decl *CondVar = nullptr;
if (ParseParenExprOrCondition(Cond, CondVar, WhileLoc, true))
return StmtError();
FullExprArg FullCond(Actions.MakeFullExpr(Cond.get(), WhileLoc));
- // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
+ // C99 6.8.5p5 - In C99, the body of the while statement is a scope, even if
// there is no compound stmt. C90 does not have this clause. We only do this
// if the body isn't a compound statement to avoid push/pop in common cases.
//
@@ -1291,8 +1335,7 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) {
// See comments in ParseIfStatement for why we create a scope for the
// condition and a new scope for substatement in C++.
//
- ParseScope InnerScope(this, Scope::DeclScope,
- C99orCXX && Tok.isNot(tok::l_brace));
+ ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
// Read the body statement.
StmtResult Body(ParseStatement(TrailingElseLoc));
@@ -1325,7 +1368,7 @@ StmtResult Parser::ParseDoStatement() {
ParseScope DoScope(this, ScopeFlags);
- // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
+ // C99 6.8.5p5 - In C99, the body of the do statement is a scope, even if
// there is no compound stmt. C90 does not have this clause. We only do this
// if the body isn't a compound statement to avoid push/pop in common cases.
//
@@ -1333,9 +1376,8 @@ StmtResult Parser::ParseDoStatement() {
// The substatement in an iteration-statement implicitly defines a local scope
// which is entered and exited each time through the loop.
//
- ParseScope InnerScope(this, Scope::DeclScope,
- (getLangOpts().C99 || getLangOpts().CPlusPlus) &&
- Tok.isNot(tok::l_brace));
+ bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
+ ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
// Read the body statement.
StmtResult Body(ParseStatement());
@@ -1346,7 +1388,7 @@ StmtResult Parser::ParseDoStatement() {
if (Tok.isNot(tok::kw_while)) {
if (!Body.isInvalid()) {
Diag(Tok, diag::err_expected_while);
- Diag(DoLoc, diag::note_matching) << "do";
+ Diag(DoLoc, diag::note_matching) << "'do'";
SkipUntil(tok::semi, StopBeforeMatch);
}
return StmtError();
@@ -1377,6 +1419,25 @@ StmtResult Parser::ParseDoStatement() {
Cond.get(), T.getCloseLocation());
}
+bool Parser::isForRangeIdentifier() {
+ assert(Tok.is(tok::identifier));
+
+ const Token &Next = NextToken();
+ if (Next.is(tok::colon))
+ return true;
+
+ if (Next.is(tok::l_square) || Next.is(tok::kw_alignas)) {
+ TentativeParsingAction PA(*this);
+ ConsumeToken();
+ SkipCXX11Attributes();
+ bool Result = Tok.is(tok::colon);
+ PA.Revert();
+ return Result;
+ }
+
+ return false;
+}
+
/// ParseForStatement
/// for-statement: [C99 6.8.5.3]
/// 'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
@@ -1424,12 +1485,9 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
// Names declared in the for-init-statement are in the same declarative-region
// as those declared in the condition.
//
- unsigned ScopeFlags;
+ unsigned ScopeFlags = 0;
if (C99orCXXorObjC)
- ScopeFlags = Scope::BreakScope | Scope::ContinueScope |
- Scope::DeclScope | Scope::ControlScope;
- else
- ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
+ ScopeFlags = Scope::DeclScope | Scope::ControlScope;
ParseScope ForScope(this, ScopeFlags);
@@ -1445,7 +1503,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
ExprResult Collection;
ForRangeInit ForRangeInit;
FullExprArg ThirdPart(Actions);
- Decl *SecondVar = 0;
+ Decl *SecondVar = nullptr;
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteOrdinaryName(getCurScope(),
@@ -1463,6 +1521,29 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
ProhibitAttributes(attrs);
// no first part, eat the ';'.
ConsumeToken();
+ } else if (getLangOpts().CPlusPlus && Tok.is(tok::identifier) &&
+ isForRangeIdentifier()) {
+ ProhibitAttributes(attrs);
+ IdentifierInfo *Name = Tok.getIdentifierInfo();
+ SourceLocation Loc = ConsumeToken();
+ MaybeParseCXX11Attributes(attrs);
+
+ ForRangeInit.ColonLoc = ConsumeToken();
+ if (Tok.is(tok::l_brace))
+ ForRangeInit.RangeExpr = ParseBraceInitializer();
+ else
+ ForRangeInit.RangeExpr = ParseExpression();
+
+ Diag(Loc, getLangOpts().CPlusPlus1z
+ ? diag::warn_cxx1y_compat_for_range_identifier
+ : diag::ext_for_range_identifier)
+ << ((getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus1z)
+ ? FixItHint::CreateInsertion(Loc, "auto &&")
+ : FixItHint());
+
+ FirstPart = Actions.ActOnCXXForRangeIdentifier(getCurScope(), Loc, Name,
+ attrs, attrs.Range.getEnd());
+ ForRange = true;
} else if (isForInitDeclaration()) { // for (int X = 4;
// Parse declaration, which eats the ';'.
if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode?
@@ -1474,12 +1555,10 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
StmtVector Stmts;
- DeclGroupPtrTy DG = ParseSimpleDeclaration(Stmts, Declarator::ForContext,
- DeclEnd, attrs, false,
- MightBeForRangeStmt ?
- &ForRangeInit : 0);
+ DeclGroupPtrTy DG = ParseSimpleDeclaration(
+ Stmts, Declarator::ForContext, DeclEnd, attrs, false,
+ MightBeForRangeStmt ? &ForRangeInit : nullptr);
FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
-
if (ForRangeInit.ParsedForRangeDecl()) {
Diag(ForRangeInit.ColonLoc, getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_for_range : diag::ext_for_range);
@@ -1544,6 +1623,9 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
}
}
}
+
+ // Parse the second part of the for specifier.
+ getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope);
if (!ForEach && !ForRange) {
assert(!SecondPart.get() && "Shouldn't have a second expression yet.");
// Parse the second part of the for specifier.
@@ -1582,7 +1664,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
ExprResult Third = ParseExpression();
// FIXME: The C++11 standard doesn't actually say that this is a
// discarded-value expression, but it clearly should be.
- ThirdPart = Actions.MakeFullDiscardedValueExpr(Third.take());
+ ThirdPart = Actions.MakeFullDiscardedValueExpr(Third.get());
}
}
// Match the ')'.
@@ -1595,7 +1677,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
StmtResult ForEachStmt;
if (ForRange) {
- ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, FirstPart.take(),
+ ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, FirstPart.get(),
ForRangeInit.ColonLoc,
ForRangeInit.RangeExpr.get(),
T.getCloseLocation(),
@@ -1606,12 +1688,12 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
// statement immediately in order to close over temporaries correctly.
} else if (ForEach) {
ForEachStmt = Actions.ActOnObjCForCollectionStmt(ForLoc,
- FirstPart.take(),
- Collection.take(),
+ FirstPart.get(),
+ Collection.get(),
T.getCloseLocation());
}
- // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
+ // C99 6.8.5p5 - In C99, the body of the for statement is a scope, even if
// there is no compound stmt. C90 does not have this clause. We only do this
// if the body isn't a compound statement to avoid push/pop in common cases.
//
@@ -1622,8 +1704,15 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
// See comments in ParseIfStatement for why we create a scope for
// for-init-statement/condition and a new scope for substatement in C++.
//
- ParseScope InnerScope(this, Scope::DeclScope,
- C99orCXXorObjC && Tok.isNot(tok::l_brace));
+ ParseScope InnerScope(this, Scope::DeclScope, C99orCXXorObjC,
+ Tok.is(tok::l_brace));
+
+ // The body of the for loop has the same local mangling number as the
+ // for-init-statement.
+ // 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();
// Read the body statement.
StmtResult Body(ParseStatement(TrailingElseLoc));
@@ -1638,15 +1727,15 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
return StmtError();
if (ForEach)
- return Actions.FinishObjCForCollectionStmt(ForEachStmt.take(),
- Body.take());
+ return Actions.FinishObjCForCollectionStmt(ForEachStmt.get(),
+ Body.get());
if (ForRange)
- return Actions.FinishCXXForRangeStmt(ForRangeStmt.take(), Body.take());
+ return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get());
- return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.take(),
+ return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(),
SecondPart, SecondVar, ThirdPart,
- T.getCloseLocation(), Body.take());
+ T.getCloseLocation(), Body.get());
}
/// ParseGotoStatement
@@ -1675,9 +1764,9 @@ StmtResult Parser::ParseGotoStatement() {
SkipUntil(tok::semi, StopBeforeMatch);
return StmtError();
}
- Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.take());
+ Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.get());
} else {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
return StmtError();
}
@@ -1730,713 +1819,40 @@ StmtResult Parser::ParseReturnStatement() {
<< R.get()->getSourceRange();
} else
R = ParseExpression();
- if (R.isInvalid()) { // Skip to the semicolon, but don't consume it.
- SkipUntil(tok::semi, StopBeforeMatch);
+ if (R.isInvalid()) {
+ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
return StmtError();
}
}
- return Actions.ActOnReturnStmt(ReturnLoc, R.take());
-}
-
-namespace {
- class ClangAsmParserCallback : public llvm::MCAsmParserSemaCallback {
- Parser &TheParser;
- SourceLocation AsmLoc;
- StringRef AsmString;
-
- /// The tokens we streamed into AsmString and handed off to MC.
- ArrayRef<Token> AsmToks;
-
- /// The offset of each token in AsmToks within AsmString.
- ArrayRef<unsigned> AsmTokOffsets;
-
- public:
- ClangAsmParserCallback(Parser &P, SourceLocation Loc,
- StringRef AsmString,
- ArrayRef<Token> Toks,
- ArrayRef<unsigned> Offsets)
- : TheParser(P), AsmLoc(Loc), AsmString(AsmString),
- AsmToks(Toks), AsmTokOffsets(Offsets) {
- assert(AsmToks.size() == AsmTokOffsets.size());
- }
-
- void *LookupInlineAsmIdentifier(StringRef &LineBuf,
- InlineAsmIdentifierInfo &Info,
- bool IsUnevaluatedContext) {
- // Collect the desired tokens.
- SmallVector<Token, 16> LineToks;
- const Token *FirstOrigToken = 0;
- findTokensForString(LineBuf, LineToks, FirstOrigToken);
-
- unsigned NumConsumedToks;
- ExprResult Result =
- TheParser.ParseMSAsmIdentifier(LineToks, NumConsumedToks, &Info,
- IsUnevaluatedContext);
-
- // If we consumed the entire line, tell MC that.
- // Also do this if we consumed nothing as a way of reporting failure.
- if (NumConsumedToks == 0 || NumConsumedToks == LineToks.size()) {
- // By not modifying LineBuf, we're implicitly consuming it all.
-
- // Otherwise, consume up to the original tokens.
- } else {
- assert(FirstOrigToken && "not using original tokens?");
-
- // Since we're using original tokens, apply that offset.
- assert(FirstOrigToken[NumConsumedToks].getLocation()
- == LineToks[NumConsumedToks].getLocation());
- unsigned FirstIndex = FirstOrigToken - AsmToks.begin();
- unsigned LastIndex = FirstIndex + NumConsumedToks - 1;
-
- // The total length we've consumed is the relative offset
- // of the last token we consumed plus its length.
- unsigned TotalOffset = (AsmTokOffsets[LastIndex]
- + AsmToks[LastIndex].getLength()
- - AsmTokOffsets[FirstIndex]);
- LineBuf = LineBuf.substr(0, TotalOffset);
- }
-
- // Initialize the "decl" with the lookup result.
- Info.OpDecl = static_cast<void*>(Result.take());
- return Info.OpDecl;
- }
-
- bool LookupInlineAsmField(StringRef Base, StringRef Member,
- unsigned &Offset) {
- return TheParser.getActions().LookupInlineAsmField(Base, Member,
- Offset, AsmLoc);
- }
-
- static void DiagHandlerCallback(const llvm::SMDiagnostic &D,
- void *Context) {
- ((ClangAsmParserCallback*) Context)->handleDiagnostic(D);
- }
-
- private:
- /// Collect the appropriate tokens for the given string.
- void findTokensForString(StringRef Str, SmallVectorImpl<Token> &TempToks,
- const Token *&FirstOrigToken) const {
- // For now, assert that the string we're working with is a substring
- // of what we gave to MC. This lets us use the original tokens.
- assert(!std::less<const char*>()(Str.begin(), AsmString.begin()) &&
- !std::less<const char*>()(AsmString.end(), Str.end()));
-
- // Try to find a token whose offset matches the first token.
- unsigned FirstCharOffset = Str.begin() - AsmString.begin();
- const unsigned *FirstTokOffset
- = std::lower_bound(AsmTokOffsets.begin(), AsmTokOffsets.end(),
- FirstCharOffset);
-
- // For now, assert that the start of the string exactly
- // corresponds to the start of a token.
- assert(*FirstTokOffset == FirstCharOffset);
-
- // Use all the original tokens for this line. (We assume the
- // end of the line corresponds cleanly to a token break.)
- unsigned FirstTokIndex = FirstTokOffset - AsmTokOffsets.begin();
- FirstOrigToken = &AsmToks[FirstTokIndex];
- unsigned LastCharOffset = Str.end() - AsmString.begin();
- for (unsigned i = FirstTokIndex, e = AsmTokOffsets.size(); i != e; ++i) {
- if (AsmTokOffsets[i] >= LastCharOffset) break;
- TempToks.push_back(AsmToks[i]);
- }
- }
-
- void handleDiagnostic(const llvm::SMDiagnostic &D) {
- // Compute an offset into the inline asm buffer.
- // FIXME: This isn't right if .macro is involved (but hopefully, no
- // real-world code does that).
- const llvm::SourceMgr &LSM = *D.getSourceMgr();
- const llvm::MemoryBuffer *LBuf =
- LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
- unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart();
-
- // Figure out which token that offset points into.
- const unsigned *TokOffsetPtr =
- std::lower_bound(AsmTokOffsets.begin(), AsmTokOffsets.end(), Offset);
- unsigned TokIndex = TokOffsetPtr - AsmTokOffsets.begin();
- unsigned TokOffset = *TokOffsetPtr;
-
- // If we come up with an answer which seems sane, use it; otherwise,
- // just point at the __asm keyword.
- // FIXME: Assert the answer is sane once we handle .macro correctly.
- SourceLocation Loc = AsmLoc;
- if (TokIndex < AsmToks.size()) {
- const Token &Tok = AsmToks[TokIndex];
- Loc = Tok.getLocation();
- Loc = Loc.getLocWithOffset(Offset - TokOffset);
- }
- TheParser.Diag(Loc, diag::err_inline_ms_asm_parsing)
- << D.getMessage();
- }
- };
-}
-
-/// Parse an identifier in an MS-style inline assembly block.
-///
-/// \param CastInfo - a void* so that we don't have to teach Parser.h
-/// about the actual type.
-ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
- unsigned &NumLineToksConsumed,
- void *CastInfo,
- bool IsUnevaluatedContext) {
- llvm::InlineAsmIdentifierInfo &Info =
- *(llvm::InlineAsmIdentifierInfo *) CastInfo;
-
- // Push a fake token on the end so that we don't overrun the token
- // stream. We use ';' because it expression-parsing should never
- // overrun it.
- const tok::TokenKind EndOfStream = tok::semi;
- Token EndOfStreamTok;
- EndOfStreamTok.startToken();
- EndOfStreamTok.setKind(EndOfStream);
- LineToks.push_back(EndOfStreamTok);
-
- // Also copy the current token over.
- LineToks.push_back(Tok);
-
- PP.EnterTokenStream(LineToks.begin(),
- LineToks.size(),
- /*disable macros*/ true,
- /*owns tokens*/ false);
-
- // Clear the current token and advance to the first token in LineToks.
- ConsumeAnyToken();
-
- // Parse an optional scope-specifier if we're in C++.
- CXXScopeSpec SS;
- if (getLangOpts().CPlusPlus) {
- ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
- }
-
- // Require an identifier here.
- SourceLocation TemplateKWLoc;
- UnqualifiedId Id;
- bool Invalid = ParseUnqualifiedId(SS,
- /*EnteringContext=*/false,
- /*AllowDestructorName=*/false,
- /*AllowConstructorName=*/false,
- /*ObjectType=*/ ParsedType(),
- TemplateKWLoc,
- Id);
-
- // If we've run into the poison token we inserted before, or there
- // was a parsing error, then claim the entire line.
- if (Invalid || Tok.is(EndOfStream)) {
- NumLineToksConsumed = LineToks.size() - 2;
-
- // Otherwise, claim up to the start of the next token.
- } else {
- // Figure out how many tokens we are into LineToks.
- unsigned LineIndex = 0;
- while (LineToks[LineIndex].getLocation() != Tok.getLocation()) {
- LineIndex++;
- assert(LineIndex < LineToks.size() - 2); // we added two extra tokens
- }
-
- NumLineToksConsumed = LineIndex;
- }
-
- // Finally, restore the old parsing state by consuming all the
- // tokens we staged before, implicitly killing off the
- // token-lexer we pushed.
- for (unsigned n = LineToks.size() - 2 - NumLineToksConsumed; n != 0; --n) {
- ConsumeAnyToken();
- }
- ConsumeToken(EndOfStream);
-
- // Leave LineToks in its original state.
- LineToks.pop_back();
- LineToks.pop_back();
-
- // Perform the lookup.
- return Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info,
- IsUnevaluatedContext);
+ return Actions.ActOnReturnStmt(ReturnLoc, R.get(), getCurScope());
}
-/// Turn a sequence of our tokens back into a string that we can hand
-/// to the MC asm parser.
-static bool buildMSAsmString(Preprocessor &PP,
- SourceLocation AsmLoc,
- ArrayRef<Token> AsmToks,
- SmallVectorImpl<unsigned> &TokOffsets,
- SmallString<512> &Asm) {
- assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!");
-
- // Is this the start of a new assembly statement?
- bool isNewStatement = true;
-
- for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) {
- const Token &Tok = AsmToks[i];
-
- // Start each new statement with a newline and a tab.
- if (!isNewStatement &&
- (Tok.is(tok::kw_asm) || Tok.isAtStartOfLine())) {
- Asm += "\n\t";
- isNewStatement = true;
- }
-
- // Preserve the existence of leading whitespace except at the
- // start of a statement.
- if (!isNewStatement && Tok.hasLeadingSpace())
- Asm += ' ';
+StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts, bool OnlyStatement,
+ SourceLocation *TrailingElseLoc,
+ ParsedAttributesWithRange &Attrs) {
+ // Create temporary attribute list.
+ ParsedAttributesWithRange TempAttrs(AttrFactory);
- // Remember the offset of this token.
- TokOffsets.push_back(Asm.size());
-
- // Don't actually write '__asm' into the assembly stream.
- if (Tok.is(tok::kw_asm)) {
- // Complain about __asm at the end of the stream.
- if (i + 1 == e) {
- PP.Diag(AsmLoc, diag::err_asm_empty);
- return true;
- }
-
- continue;
- }
-
- // Append the spelling of the token.
- SmallString<32> SpellingBuffer;
- bool SpellingInvalid = false;
- Asm += PP.getSpelling(Tok, SpellingBuffer, &SpellingInvalid);
- assert(!SpellingInvalid && "spelling was invalid after correct parse?");
-
- // We are no longer at the start of a statement.
- isNewStatement = false;
- }
-
- // Ensure that the buffer is null-terminated.
- Asm.push_back('\0');
- Asm.pop_back();
-
- assert(TokOffsets.size() == AsmToks.size());
- return false;
-}
-
-/// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled,
-/// this routine is called to collect the tokens for an MS asm statement.
-///
-/// [MS] ms-asm-statement:
-/// ms-asm-block
-/// ms-asm-block ms-asm-statement
-///
-/// [MS] ms-asm-block:
-/// '__asm' ms-asm-line '\n'
-/// '__asm' '{' ms-asm-instruction-block[opt] '}' ';'[opt]
-///
-/// [MS] ms-asm-instruction-block
-/// ms-asm-line
-/// ms-asm-line '\n' ms-asm-instruction-block
-///
-StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
- SourceManager &SrcMgr = PP.getSourceManager();
- SourceLocation EndLoc = AsmLoc;
- SmallVector<Token, 4> AsmToks;
-
- bool InBraces = false;
- unsigned short savedBraceCount = 0;
- bool InAsmComment = false;
- FileID FID;
- unsigned LineNo = 0;
- unsigned NumTokensRead = 0;
- SourceLocation LBraceLoc;
-
- if (Tok.is(tok::l_brace)) {
- // Braced inline asm: consume the opening brace.
- InBraces = true;
- savedBraceCount = BraceCount;
- EndLoc = LBraceLoc = ConsumeBrace();
- ++NumTokensRead;
- } else {
- // Single-line inline asm; compute which line it is on.
- std::pair<FileID, unsigned> ExpAsmLoc =
- SrcMgr.getDecomposedExpansionLoc(EndLoc);
- FID = ExpAsmLoc.first;
- LineNo = SrcMgr.getLineNumber(FID, ExpAsmLoc.second);
- }
-
- SourceLocation TokLoc = Tok.getLocation();
- do {
- // If we hit EOF, we're done, period.
- if (Tok.is(tok::eof))
- break;
-
- if (!InAsmComment && Tok.is(tok::semi)) {
- // A semicolon in an asm is the start of a comment.
- InAsmComment = true;
- if (InBraces) {
- // Compute which line the comment is on.
- std::pair<FileID, unsigned> ExpSemiLoc =
- SrcMgr.getDecomposedExpansionLoc(TokLoc);
- FID = ExpSemiLoc.first;
- LineNo = SrcMgr.getLineNumber(FID, ExpSemiLoc.second);
- }
- } else if (!InBraces || InAsmComment) {
- // If end-of-line is significant, check whether this token is on a
- // new line.
- std::pair<FileID, unsigned> ExpLoc =
- SrcMgr.getDecomposedExpansionLoc(TokLoc);
- if (ExpLoc.first != FID ||
- SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) {
- // If this is a single-line __asm, we're done.
- if (!InBraces)
- break;
- // We're no longer in a comment.
- InAsmComment = false;
- } else if (!InAsmComment && Tok.is(tok::r_brace)) {
- // Single-line asm always ends when a closing brace is seen.
- // FIXME: This is compatible with Apple gcc's -fasm-blocks; what
- // does MSVC do here?
- break;
- }
- }
- if (!InAsmComment && InBraces && Tok.is(tok::r_brace) &&
- BraceCount == (savedBraceCount + 1)) {
- // Consume the closing brace, and finish
- EndLoc = ConsumeBrace();
- break;
- }
-
- // Consume the next token; make sure we don't modify the brace count etc.
- // if we are in a comment.
- EndLoc = TokLoc;
- if (InAsmComment)
- PP.Lex(Tok);
- else {
- AsmToks.push_back(Tok);
- ConsumeAnyToken();
- }
- TokLoc = Tok.getLocation();
- ++NumTokensRead;
- } while (1);
-
- if (InBraces && BraceCount != savedBraceCount) {
- // __asm without closing brace (this can happen at EOF).
- Diag(Tok, diag::err_expected_rbrace);
- Diag(LBraceLoc, diag::note_matching) << "{";
- return StmtError();
- } else if (NumTokensRead == 0) {
- // Empty __asm.
- Diag(Tok, diag::err_expected_lbrace);
- return StmtError();
- }
-
- // Okay, prepare to use MC to parse the assembly.
- SmallVector<StringRef, 4> ConstraintRefs;
- SmallVector<Expr*, 4> Exprs;
- SmallVector<StringRef, 4> ClobberRefs;
-
- // We need an actual supported target.
- llvm::Triple TheTriple = Actions.Context.getTargetInfo().getTriple();
- llvm::Triple::ArchType ArchTy = TheTriple.getArch();
- const std::string &TT = TheTriple.getTriple();
- const llvm::Target *TheTarget = 0;
- bool UnsupportedArch = (ArchTy != llvm::Triple::x86 &&
- ArchTy != llvm::Triple::x86_64);
- if (UnsupportedArch) {
- Diag(AsmLoc, diag::err_msasm_unsupported_arch) << TheTriple.getArchName();
- } else {
- std::string Error;
- TheTarget = llvm::TargetRegistry::lookupTarget(TT, Error);
- if (!TheTarget)
- Diag(AsmLoc, diag::err_msasm_unable_to_create_target) << Error;
- }
-
- // If we don't support assembly, or the assembly is empty, we don't
- // need to instantiate the AsmParser, etc.
- if (!TheTarget || AsmToks.empty()) {
- return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLoc, AsmToks, StringRef(),
- /*NumOutputs*/ 0, /*NumInputs*/ 0,
- ConstraintRefs, ClobberRefs, Exprs, EndLoc);
- }
-
- // Expand the tokens into a string buffer.
- SmallString<512> AsmString;
- SmallVector<unsigned, 8> TokOffsets;
- if (buildMSAsmString(PP, AsmLoc, AsmToks, TokOffsets, AsmString))
- return StmtError();
-
- OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
- OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT));
- // Get the instruction descriptor.
- const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo();
- OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
- OwningPtr<llvm::MCSubtargetInfo>
- STI(TheTarget->createMCSubtargetInfo(TT, "", ""));
-
- llvm::SourceMgr TempSrcMgr;
- llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr);
- llvm::MemoryBuffer *Buffer =
- llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS inline asm>");
-
- // Tell SrcMgr about this buffer, which is what the parser will pick up.
- TempSrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc());
-
- OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
- OwningPtr<llvm::MCAsmParser>
- Parser(createMCAsmParser(TempSrcMgr, Ctx, *Str.get(), *MAI));
- OwningPtr<llvm::MCTargetAsmParser>
- TargetParser(TheTarget->createMCAsmParser(*STI, *Parser, *MII));
-
- llvm::MCInstPrinter *IP =
- TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI);
-
- // Change to the Intel dialect.
- Parser->setAssemblerDialect(1);
- Parser->setTargetParser(*TargetParser.get());
- Parser->setParsingInlineAsm(true);
- TargetParser->setParsingInlineAsm(true);
-
- ClangAsmParserCallback Callback(*this, AsmLoc, AsmString,
- AsmToks, TokOffsets);
- TargetParser->setSemaCallback(&Callback);
- TempSrcMgr.setDiagHandler(ClangAsmParserCallback::DiagHandlerCallback,
- &Callback);
-
- unsigned NumOutputs;
- unsigned NumInputs;
- std::string AsmStringIR;
- SmallVector<std::pair<void *, bool>, 4> OpExprs;
- SmallVector<std::string, 4> Constraints;
- SmallVector<std::string, 4> Clobbers;
- if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR,
- NumOutputs, NumInputs, OpExprs, Constraints,
- Clobbers, MII, IP, Callback))
- return StmtError();
-
- // Build the vector of clobber StringRefs.
- unsigned NumClobbers = Clobbers.size();
- ClobberRefs.resize(NumClobbers);
- for (unsigned i = 0; i != NumClobbers; ++i)
- ClobberRefs[i] = StringRef(Clobbers[i]);
-
- // Recast the void pointers and build the vector of constraint StringRefs.
- unsigned NumExprs = NumOutputs + NumInputs;
- ConstraintRefs.resize(NumExprs);
- Exprs.resize(NumExprs);
- for (unsigned i = 0, e = NumExprs; i != e; ++i) {
- Expr *OpExpr = static_cast<Expr *>(OpExprs[i].first);
- if (!OpExpr)
- return StmtError();
-
- // Need address of variable.
- if (OpExprs[i].second)
- OpExpr = Actions.BuildUnaryOp(getCurScope(), AsmLoc, UO_AddrOf, OpExpr)
- .take();
-
- ConstraintRefs[i] = StringRef(Constraints[i]);
- Exprs[i] = OpExpr;
- }
-
- // FIXME: We should be passing source locations for better diagnostics.
- return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLoc, AsmToks, AsmStringIR,
- NumOutputs, NumInputs,
- ConstraintRefs, ClobberRefs, Exprs, EndLoc);
-}
-
-/// ParseAsmStatement - Parse a GNU extended asm statement.
-/// asm-statement:
-/// gnu-asm-statement
-/// ms-asm-statement
-///
-/// [GNU] gnu-asm-statement:
-/// 'asm' type-qualifier[opt] '(' asm-argument ')' ';'
-///
-/// [GNU] asm-argument:
-/// asm-string-literal
-/// asm-string-literal ':' asm-operands[opt]
-/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
-/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
-/// ':' asm-clobbers
-///
-/// [GNU] asm-clobbers:
-/// asm-string-literal
-/// asm-clobbers ',' asm-string-literal
-///
-StmtResult Parser::ParseAsmStatement(bool &msAsm) {
- assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
- SourceLocation AsmLoc = ConsumeToken();
-
- if (getLangOpts().AsmBlocks && Tok.isNot(tok::l_paren) &&
- !isTypeQualifier()) {
- msAsm = true;
- return ParseMicrosoftAsmStatement(AsmLoc);
- }
- DeclSpec DS(AttrFactory);
- SourceLocation Loc = Tok.getLocation();
- ParseTypeQualifierListOpt(DS, true, false);
-
- // GNU asms accept, but warn, about type-qualifiers other than volatile.
- if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
- Diag(Loc, diag::w_asm_qualifier_ignored) << "const";
- if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
- Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict";
- // FIXME: Once GCC supports _Atomic, check whether it permits it here.
- if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
- Diag(Loc, diag::w_asm_qualifier_ignored) << "_Atomic";
-
- // Remember if this was a volatile asm.
- bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile;
- if (Tok.isNot(tok::l_paren)) {
- Diag(Tok, diag::err_expected_lparen_after) << "asm";
- SkipUntil(tok::r_paren, StopAtSemi);
- return StmtError();
- }
- BalancedDelimiterTracker T(*this, tok::l_paren);
- T.consumeOpen();
-
- ExprResult AsmString(ParseAsmStringLiteral());
- if (AsmString.isInvalid()) {
- // Consume up to and including the closing paren.
- T.skipToEnd();
- return StmtError();
- }
-
- SmallVector<IdentifierInfo *, 4> Names;
- ExprVector Constraints;
- ExprVector Exprs;
- ExprVector Clobbers;
-
- if (Tok.is(tok::r_paren)) {
- // We have a simple asm expression like 'asm("foo")'.
- T.consumeClose();
- return Actions.ActOnGCCAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile,
- /*NumOutputs*/ 0, /*NumInputs*/ 0, 0,
- Constraints, Exprs, AsmString.take(),
- Clobbers, T.getCloseLocation());
- }
-
- // Parse Outputs, if present.
- bool AteExtraColon = false;
- if (Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
- // In C++ mode, parse "::" like ": :".
- AteExtraColon = Tok.is(tok::coloncolon);
+ // Get loop hints and consume annotated token.
+ while (Tok.is(tok::annot_pragma_loop_hint)) {
+ LoopHint Hint = HandlePragmaLoopHint();
ConsumeToken();
- if (!AteExtraColon &&
- ParseAsmOperandsOpt(Names, Constraints, Exprs))
- return StmtError();
+ ArgsUnion ArgHints[] = {Hint.PragmaNameLoc, Hint.OptionLoc, Hint.ValueLoc,
+ ArgsUnion(Hint.ValueExpr)};
+ TempAttrs.addNew(Hint.PragmaNameLoc->Ident, Hint.Range, nullptr,
+ Hint.PragmaNameLoc->Loc, ArgHints, 4,
+ AttributeList::AS_Pragma);
}
- unsigned NumOutputs = Names.size();
-
- // Parse Inputs, if present.
- if (AteExtraColon ||
- Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
- // In C++ mode, parse "::" like ": :".
- if (AteExtraColon)
- AteExtraColon = false;
- else {
- AteExtraColon = Tok.is(tok::coloncolon);
- ConsumeToken();
- }
+ // Get the next statement.
+ MaybeParseCXX11Attributes(Attrs);
- if (!AteExtraColon &&
- ParseAsmOperandsOpt(Names, Constraints, Exprs))
- return StmtError();
- }
-
- assert(Names.size() == Constraints.size() &&
- Constraints.size() == Exprs.size() &&
- "Input operand size mismatch!");
-
- unsigned NumInputs = Names.size() - NumOutputs;
-
- // Parse the clobbers, if present.
- if (AteExtraColon || Tok.is(tok::colon)) {
- if (!AteExtraColon)
- ConsumeToken();
-
- // Parse the asm-string list for clobbers if present.
- if (Tok.isNot(tok::r_paren)) {
- while (1) {
- ExprResult Clobber(ParseAsmStringLiteral());
-
- if (Clobber.isInvalid())
- break;
-
- Clobbers.push_back(Clobber.release());
-
- if (Tok.isNot(tok::comma)) break;
- ConsumeToken();
- }
- }
- }
+ StmtResult S = ParseStatementOrDeclarationAfterAttributes(
+ Stmts, OnlyStatement, TrailingElseLoc, Attrs);
- T.consumeClose();
- return Actions.ActOnGCCAsmStmt(AsmLoc, false, isVolatile, NumOutputs,
- NumInputs, Names.data(), Constraints, Exprs,
- AsmString.take(), Clobbers,
- T.getCloseLocation());
-}
-
-/// ParseAsmOperands - Parse the asm-operands production as used by
-/// asm-statement, assuming the leading ':' token was eaten.
-///
-/// [GNU] asm-operands:
-/// asm-operand
-/// asm-operands ',' asm-operand
-///
-/// [GNU] asm-operand:
-/// asm-string-literal '(' expression ')'
-/// '[' identifier ']' asm-string-literal '(' expression ')'
-///
-//
-// FIXME: Avoid unnecessary std::string trashing.
-bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
- SmallVectorImpl<Expr *> &Constraints,
- SmallVectorImpl<Expr *> &Exprs) {
- // 'asm-operands' isn't present?
- if (!isTokenStringLiteral() && Tok.isNot(tok::l_square))
- return false;
-
- while (1) {
- // Read the [id] if present.
- if (Tok.is(tok::l_square)) {
- BalancedDelimiterTracker T(*this, tok::l_square);
- T.consumeOpen();
-
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
- SkipUntil(tok::r_paren, StopAtSemi);
- return true;
- }
-
- IdentifierInfo *II = Tok.getIdentifierInfo();
- ConsumeToken();
-
- Names.push_back(II);
- T.consumeClose();
- } else
- Names.push_back(0);
-
- ExprResult Constraint(ParseAsmStringLiteral());
- if (Constraint.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return true;
- }
- Constraints.push_back(Constraint.release());
-
- if (Tok.isNot(tok::l_paren)) {
- Diag(Tok, diag::err_expected_lparen_after) << "asm operand";
- SkipUntil(tok::r_paren, StopAtSemi);
- return true;
- }
-
- // Read the parenthesized expression.
- BalancedDelimiterTracker T(*this, tok::l_paren);
- T.consumeOpen();
- ExprResult Res(ParseExpression());
- T.consumeClose();
- if (Res.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return true;
- }
- Exprs.push_back(Res.release());
- // Eat the comma and continue parsing if it exists.
- if (Tok.isNot(tok::comma)) return false;
- ConsumeToken();
- }
+ Attrs.takeAllFrom(TempAttrs);
+ return S;
}
Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) {
@@ -2464,7 +1880,7 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) {
}
BodyScope.Exit();
- return Actions.ActOnFinishFunctionBody(Decl, FnBody.take());
+ return Actions.ActOnFinishFunctionBody(Decl, FnBody.get());
}
/// ParseFunctionTryBlock - Parse a C++ function-try-block.
@@ -2501,7 +1917,7 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) {
}
BodyScope.Exit();
- return Actions.ActOnFinishFunctionBody(Decl, FnBody.take());
+ return Actions.ActOnFinishFunctionBody(Decl, FnBody.get());
}
bool Parser::trySkippingFunctionBody() {
@@ -2554,16 +1970,28 @@ StmtResult Parser::ParseCXXTryBlock() {
///
/// [Borland] try-block:
/// 'try' compound-statement seh-except-block
-/// 'try' compound-statment seh-finally-block
+/// 'try' compound-statement seh-finally-block
///
StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) {
if (Tok.isNot(tok::l_brace))
- return StmtError(Diag(Tok, diag::err_expected_lbrace));
+ return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
// FIXME: Possible draft standard bug: attribute-specifier should be allowed?
- StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false,
- Scope::DeclScope | Scope::TryScope |
- (FnTry ? Scope::FnTryCatchScope : 0)));
+ int SEHTryIndex, SEHTryParentIndex;
+ StmtResult TryBlock;
+ {
+ assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
+
+ // Enter a scope to hold everything within the compound stmt. Compound
+ // statements can always hold declarations.
+ ParseScope CompoundScope(this, Scope::DeclScope | Scope::TryScope |
+ (FnTry ? Scope::FnTryCatchScope : 0));
+ SEHTryIndex = getCurScope()->getSEHTryIndex();
+ SEHTryParentIndex = getCurScope()->getSEHTryParentIndex();
+
+ // Parse the statements in the body.
+ TryBlock = ParseCompoundStatementBody();
+ }
if (TryBlock.isInvalid())
return TryBlock;
@@ -2587,8 +2015,10 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) {
return Actions.ActOnSEHTryBlock(true /* IsCXXTry */,
TryLoc,
- TryBlock.take(),
- Handler.take());
+ TryBlock.get(),
+ Handler.get(),
+ SEHTryIndex,
+ SEHTryParentIndex);
}
else {
StmtVector Handlers;
@@ -2602,14 +2032,14 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) {
while (Tok.is(tok::kw_catch)) {
StmtResult Handler(ParseCXXCatchBlock(FnTry));
if (!Handler.isInvalid())
- Handlers.push_back(Handler.release());
+ Handlers.push_back(Handler.get());
}
// Don't bother creating the full statement if we don't have any usable
// handlers.
if (Handlers.empty())
return StmtError();
- return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.take(), Handlers);
+ return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.get(), Handlers);
}
}
@@ -2629,7 +2059,7 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) {
SourceLocation CatchLoc = ConsumeToken();
BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen))
+ if (T.expectAndConsume())
return StmtError();
// C++ 3.3.2p3:
@@ -2640,7 +2070,7 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) {
// exception-declaration is equivalent to '...' or a parameter-declaration
// without default arguments.
- Decl *ExceptionDecl = 0;
+ Decl *ExceptionDecl = nullptr;
if (Tok.isNot(tok::ellipsis)) {
ParsedAttributesWithRange Attributes(AttrFactory);
MaybeParseCXX11Attributes(Attributes);
@@ -2662,14 +2092,14 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) {
return StmtError();
if (Tok.isNot(tok::l_brace))
- return StmtError(Diag(Tok, diag::err_expected_lbrace));
+ return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
// FIXME: Possible draft standard bug: attribute-specifier should be allowed?
StmtResult Block(ParseCompoundStatement());
if (Block.isInvalid())
return Block;
- return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, Block.take());
+ return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, Block.get());
}
void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) {
@@ -2683,7 +2113,7 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) {
// inside these braces escaping to the surrounding code.
if (Result.Behavior == IEB_Dependent) {
if (!Tok.is(tok::l_brace)) {
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
return;
}
@@ -2703,7 +2133,7 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) {
BalancedDelimiterTracker Braces(*this, tok::l_brace);
if (Braces.consumeOpen()) {
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
return;
}
@@ -2724,7 +2154,7 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) {
while (Tok.isNot(tok::r_brace)) {
StmtResult R = ParseStatementOrDeclaration(Stmts, false);
if (R.isUsable())
- Stmts.push_back(R.release());
+ Stmts.push_back(R.get());
}
Braces.consumeClose();
}
diff --git a/lib/Parse/ParseStmtAsm.cpp b/lib/Parse/ParseStmtAsm.cpp
new file mode 100644
index 000000000000..f7e8307883de
--- /dev/null
+++ b/lib/Parse/ParseStmtAsm.cpp
@@ -0,0 +1,761 @@
+//===---- ParseStmtAsm.cpp - Assembly Statement Parser --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements parsing for GCC and Microsoft inline assembly.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Parser.h"
+#include "RAIIObjectsForParser.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetAsmParser.h"
+#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+using namespace clang;
+
+namespace {
+class ClangAsmParserCallback : public llvm::MCAsmParserSemaCallback {
+ Parser &TheParser;
+ SourceLocation AsmLoc;
+ StringRef AsmString;
+
+ /// The tokens we streamed into AsmString and handed off to MC.
+ ArrayRef<Token> AsmToks;
+
+ /// The offset of each token in AsmToks within AsmString.
+ ArrayRef<unsigned> AsmTokOffsets;
+
+public:
+ ClangAsmParserCallback(Parser &P, SourceLocation Loc, StringRef AsmString,
+ ArrayRef<Token> Toks, ArrayRef<unsigned> Offsets)
+ : TheParser(P), AsmLoc(Loc), AsmString(AsmString), AsmToks(Toks),
+ AsmTokOffsets(Offsets) {
+ assert(AsmToks.size() == AsmTokOffsets.size());
+ }
+
+ void *LookupInlineAsmIdentifier(StringRef &LineBuf,
+ llvm::InlineAsmIdentifierInfo &Info,
+ bool IsUnevaluatedContext) override {
+ // Collect the desired tokens.
+ SmallVector<Token, 16> LineToks;
+ const Token *FirstOrigToken = nullptr;
+ findTokensForString(LineBuf, LineToks, FirstOrigToken);
+
+ unsigned NumConsumedToks;
+ ExprResult Result = TheParser.ParseMSAsmIdentifier(
+ LineToks, NumConsumedToks, &Info, IsUnevaluatedContext);
+
+ // If we consumed the entire line, tell MC that.
+ // Also do this if we consumed nothing as a way of reporting failure.
+ if (NumConsumedToks == 0 || NumConsumedToks == LineToks.size()) {
+ // By not modifying LineBuf, we're implicitly consuming it all.
+
+ // Otherwise, consume up to the original tokens.
+ } else {
+ assert(FirstOrigToken && "not using original tokens?");
+
+ // Since we're using original tokens, apply that offset.
+ assert(FirstOrigToken[NumConsumedToks].getLocation() ==
+ LineToks[NumConsumedToks].getLocation());
+ unsigned FirstIndex = FirstOrigToken - AsmToks.begin();
+ unsigned LastIndex = FirstIndex + NumConsumedToks - 1;
+
+ // The total length we've consumed is the relative offset
+ // of the last token we consumed plus its length.
+ unsigned TotalOffset =
+ (AsmTokOffsets[LastIndex] + AsmToks[LastIndex].getLength() -
+ AsmTokOffsets[FirstIndex]);
+ LineBuf = LineBuf.substr(0, TotalOffset);
+ }
+
+ // Initialize the "decl" with the lookup result.
+ Info.OpDecl = static_cast<void *>(Result.get());
+ return Info.OpDecl;
+ }
+
+ bool LookupInlineAsmField(StringRef Base, StringRef Member,
+ unsigned &Offset) override {
+ return TheParser.getActions().LookupInlineAsmField(Base, Member, Offset,
+ AsmLoc);
+ }
+
+ static void DiagHandlerCallback(const llvm::SMDiagnostic &D, void *Context) {
+ ((ClangAsmParserCallback *)Context)->handleDiagnostic(D);
+ }
+
+private:
+ /// Collect the appropriate tokens for the given string.
+ void findTokensForString(StringRef Str, SmallVectorImpl<Token> &TempToks,
+ const Token *&FirstOrigToken) const {
+ // For now, assert that the string we're working with is a substring
+ // of what we gave to MC. This lets us use the original tokens.
+ assert(!std::less<const char *>()(Str.begin(), AsmString.begin()) &&
+ !std::less<const char *>()(AsmString.end(), Str.end()));
+
+ // Try to find a token whose offset matches the first token.
+ unsigned FirstCharOffset = Str.begin() - AsmString.begin();
+ const unsigned *FirstTokOffset = std::lower_bound(
+ AsmTokOffsets.begin(), AsmTokOffsets.end(), FirstCharOffset);
+
+ // For now, assert that the start of the string exactly
+ // corresponds to the start of a token.
+ assert(*FirstTokOffset == FirstCharOffset);
+
+ // Use all the original tokens for this line. (We assume the
+ // end of the line corresponds cleanly to a token break.)
+ unsigned FirstTokIndex = FirstTokOffset - AsmTokOffsets.begin();
+ FirstOrigToken = &AsmToks[FirstTokIndex];
+ unsigned LastCharOffset = Str.end() - AsmString.begin();
+ for (unsigned i = FirstTokIndex, e = AsmTokOffsets.size(); i != e; ++i) {
+ if (AsmTokOffsets[i] >= LastCharOffset)
+ break;
+ TempToks.push_back(AsmToks[i]);
+ }
+ }
+
+ void handleDiagnostic(const llvm::SMDiagnostic &D) {
+ // Compute an offset into the inline asm buffer.
+ // FIXME: This isn't right if .macro is involved (but hopefully, no
+ // real-world code does that).
+ const llvm::SourceMgr &LSM = *D.getSourceMgr();
+ const llvm::MemoryBuffer *LBuf =
+ LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
+ unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart();
+
+ // Figure out which token that offset points into.
+ const unsigned *TokOffsetPtr =
+ std::lower_bound(AsmTokOffsets.begin(), AsmTokOffsets.end(), Offset);
+ unsigned TokIndex = TokOffsetPtr - AsmTokOffsets.begin();
+ unsigned TokOffset = *TokOffsetPtr;
+
+ // If we come up with an answer which seems sane, use it; otherwise,
+ // just point at the __asm keyword.
+ // FIXME: Assert the answer is sane once we handle .macro correctly.
+ SourceLocation Loc = AsmLoc;
+ if (TokIndex < AsmToks.size()) {
+ const Token &Tok = AsmToks[TokIndex];
+ Loc = Tok.getLocation();
+ Loc = Loc.getLocWithOffset(Offset - TokOffset);
+ }
+ TheParser.Diag(Loc, diag::err_inline_ms_asm_parsing) << D.getMessage();
+ }
+};
+}
+
+/// Parse an identifier in an MS-style inline assembly block.
+///
+/// \param CastInfo - a void* so that we don't have to teach Parser.h
+/// about the actual type.
+ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
+ unsigned &NumLineToksConsumed,
+ void *CastInfo,
+ bool IsUnevaluatedContext) {
+ llvm::InlineAsmIdentifierInfo &Info =
+ *(llvm::InlineAsmIdentifierInfo *)CastInfo;
+
+ // Push a fake token on the end so that we don't overrun the token
+ // stream. We use ';' because it expression-parsing should never
+ // overrun it.
+ const tok::TokenKind EndOfStream = tok::semi;
+ Token EndOfStreamTok;
+ EndOfStreamTok.startToken();
+ EndOfStreamTok.setKind(EndOfStream);
+ LineToks.push_back(EndOfStreamTok);
+
+ // Also copy the current token over.
+ LineToks.push_back(Tok);
+
+ PP.EnterTokenStream(LineToks.begin(), LineToks.size(),
+ /*disable macros*/ true,
+ /*owns tokens*/ false);
+
+ // Clear the current token and advance to the first token in LineToks.
+ ConsumeAnyToken();
+
+ // Parse an optional scope-specifier if we're in C++.
+ CXXScopeSpec SS;
+ if (getLangOpts().CPlusPlus) {
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
+ }
+
+ // Require an identifier here.
+ SourceLocation TemplateKWLoc;
+ UnqualifiedId Id;
+ bool Invalid =
+ ParseUnqualifiedId(SS,
+ /*EnteringContext=*/false,
+ /*AllowDestructorName=*/false,
+ /*AllowConstructorName=*/false,
+ /*ObjectType=*/ParsedType(), TemplateKWLoc, Id);
+
+ // Figure out how many tokens we are into LineToks.
+ unsigned LineIndex = 0;
+ if (Tok.is(EndOfStream)) {
+ LineIndex = LineToks.size() - 2;
+ } else {
+ while (LineToks[LineIndex].getLocation() != Tok.getLocation()) {
+ LineIndex++;
+ assert(LineIndex < LineToks.size() - 2); // we added two extra tokens
+ }
+ }
+
+ // If we've run into the poison token we inserted before, or there
+ // was a parsing error, then claim the entire line.
+ if (Invalid || Tok.is(EndOfStream)) {
+ NumLineToksConsumed = LineToks.size() - 2;
+ } else {
+ // Otherwise, claim up to the start of the next token.
+ NumLineToksConsumed = LineIndex;
+ }
+
+ // Finally, restore the old parsing state by consuming all the tokens we
+ // staged before, implicitly killing off the token-lexer we pushed.
+ for (unsigned i = 0, e = LineToks.size() - LineIndex - 2; i != e; ++i) {
+ ConsumeAnyToken();
+ }
+ assert(Tok.is(EndOfStream));
+ ConsumeToken();
+
+ // Leave LineToks in its original state.
+ LineToks.pop_back();
+ LineToks.pop_back();
+
+ // Perform the lookup.
+ return Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info,
+ IsUnevaluatedContext);
+}
+
+/// Turn a sequence of our tokens back into a string that we can hand
+/// to the MC asm parser.
+static bool buildMSAsmString(Preprocessor &PP, SourceLocation AsmLoc,
+ ArrayRef<Token> AsmToks,
+ SmallVectorImpl<unsigned> &TokOffsets,
+ SmallString<512> &Asm) {
+ assert(!AsmToks.empty() && "Didn't expect an empty AsmToks!");
+
+ // Is this the start of a new assembly statement?
+ bool isNewStatement = true;
+
+ for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) {
+ const Token &Tok = AsmToks[i];
+
+ // Start each new statement with a newline and a tab.
+ if (!isNewStatement && (Tok.is(tok::kw_asm) || Tok.isAtStartOfLine())) {
+ Asm += "\n\t";
+ isNewStatement = true;
+ }
+
+ // Preserve the existence of leading whitespace except at the
+ // start of a statement.
+ if (!isNewStatement && Tok.hasLeadingSpace())
+ Asm += ' ';
+
+ // Remember the offset of this token.
+ TokOffsets.push_back(Asm.size());
+
+ // Don't actually write '__asm' into the assembly stream.
+ if (Tok.is(tok::kw_asm)) {
+ // Complain about __asm at the end of the stream.
+ if (i + 1 == e) {
+ PP.Diag(AsmLoc, diag::err_asm_empty);
+ return true;
+ }
+
+ continue;
+ }
+
+ // Append the spelling of the token.
+ SmallString<32> SpellingBuffer;
+ bool SpellingInvalid = false;
+ Asm += PP.getSpelling(Tok, SpellingBuffer, &SpellingInvalid);
+ assert(!SpellingInvalid && "spelling was invalid after correct parse?");
+
+ // We are no longer at the start of a statement.
+ isNewStatement = false;
+ }
+
+ // Ensure that the buffer is null-terminated.
+ Asm.push_back('\0');
+ Asm.pop_back();
+
+ assert(TokOffsets.size() == AsmToks.size());
+ return false;
+}
+
+/// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled,
+/// this routine is called to collect the tokens for an MS asm statement.
+///
+/// [MS] ms-asm-statement:
+/// ms-asm-block
+/// ms-asm-block ms-asm-statement
+///
+/// [MS] ms-asm-block:
+/// '__asm' ms-asm-line '\n'
+/// '__asm' '{' ms-asm-instruction-block[opt] '}' ';'[opt]
+///
+/// [MS] ms-asm-instruction-block
+/// ms-asm-line
+/// ms-asm-line '\n' ms-asm-instruction-block
+///
+StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
+ SourceManager &SrcMgr = PP.getSourceManager();
+ SourceLocation EndLoc = AsmLoc;
+ SmallVector<Token, 4> AsmToks;
+
+ unsigned BraceNesting = 0;
+ unsigned short savedBraceCount = BraceCount;
+ bool InAsmComment = false;
+ FileID FID;
+ unsigned LineNo = 0;
+ unsigned NumTokensRead = 0;
+ SmallVector<SourceLocation, 4> LBraceLocs;
+ bool SkippedStartOfLine = false;
+
+ if (Tok.is(tok::l_brace)) {
+ // Braced inline asm: consume the opening brace.
+ BraceNesting = 1;
+ EndLoc = ConsumeBrace();
+ LBraceLocs.push_back(EndLoc);
+ ++NumTokensRead;
+ } else {
+ // Single-line inline asm; compute which line it is on.
+ std::pair<FileID, unsigned> ExpAsmLoc =
+ SrcMgr.getDecomposedExpansionLoc(EndLoc);
+ FID = ExpAsmLoc.first;
+ LineNo = SrcMgr.getLineNumber(FID, ExpAsmLoc.second);
+ LBraceLocs.push_back(SourceLocation());
+ }
+
+ SourceLocation TokLoc = Tok.getLocation();
+ do {
+ // If we hit EOF, we're done, period.
+ if (isEofOrEom())
+ break;
+
+ if (!InAsmComment && Tok.is(tok::l_brace)) {
+ // Consume the opening brace.
+ SkippedStartOfLine = Tok.isAtStartOfLine();
+ EndLoc = ConsumeBrace();
+ BraceNesting++;
+ LBraceLocs.push_back(EndLoc);
+ TokLoc = Tok.getLocation();
+ ++NumTokensRead;
+ continue;
+ } else if (!InAsmComment && Tok.is(tok::semi)) {
+ // A semicolon in an asm is the start of a comment.
+ InAsmComment = true;
+ if (BraceNesting) {
+ // Compute which line the comment is on.
+ std::pair<FileID, unsigned> ExpSemiLoc =
+ SrcMgr.getDecomposedExpansionLoc(TokLoc);
+ FID = ExpSemiLoc.first;
+ LineNo = SrcMgr.getLineNumber(FID, ExpSemiLoc.second);
+ }
+ } else if (!BraceNesting || InAsmComment) {
+ // If end-of-line is significant, check whether this token is on a
+ // new line.
+ std::pair<FileID, unsigned> ExpLoc =
+ SrcMgr.getDecomposedExpansionLoc(TokLoc);
+ if (ExpLoc.first != FID ||
+ SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) {
+ // If this is a single-line __asm, we're done.
+ if (!BraceNesting)
+ break;
+ // We're no longer in a comment.
+ InAsmComment = false;
+ } else if (!InAsmComment && Tok.is(tok::r_brace)) {
+ // Single-line asm always ends when a closing brace is seen.
+ // FIXME: This is compatible with Apple gcc's -fasm-blocks; what
+ // does MSVC do here?
+ break;
+ }
+ }
+ if (!InAsmComment && BraceNesting && Tok.is(tok::r_brace) &&
+ BraceCount == (savedBraceCount + BraceNesting)) {
+ // Consume the closing brace.
+ SkippedStartOfLine = Tok.isAtStartOfLine();
+ EndLoc = ConsumeBrace();
+ BraceNesting--;
+ // Finish if all of the opened braces in the inline asm section were
+ // consumed.
+ if (BraceNesting == 0)
+ break;
+ else {
+ LBraceLocs.pop_back();
+ TokLoc = Tok.getLocation();
+ ++NumTokensRead;
+ continue;
+ }
+ }
+
+ // Consume the next token; make sure we don't modify the brace count etc.
+ // if we are in a comment.
+ EndLoc = TokLoc;
+ if (InAsmComment)
+ PP.Lex(Tok);
+ else {
+ // Set the token as the start of line if we skipped the original start
+ // of line token in case it was a nested brace.
+ if (SkippedStartOfLine)
+ Tok.setFlag(Token::StartOfLine);
+ AsmToks.push_back(Tok);
+ ConsumeAnyToken();
+ }
+ TokLoc = Tok.getLocation();
+ ++NumTokensRead;
+ SkippedStartOfLine = false;
+ } while (1);
+
+ if (BraceNesting && BraceCount != savedBraceCount) {
+ // __asm without closing brace (this can happen at EOF).
+ for (unsigned i = 0; i < BraceNesting; ++i) {
+ Diag(Tok, diag::err_expected) << tok::r_brace;
+ Diag(LBraceLocs.back(), diag::note_matching) << tok::l_brace;
+ LBraceLocs.pop_back();
+ }
+ return StmtError();
+ } else if (NumTokensRead == 0) {
+ // Empty __asm.
+ Diag(Tok, diag::err_expected) << tok::l_brace;
+ return StmtError();
+ }
+
+ // Okay, prepare to use MC to parse the assembly.
+ SmallVector<StringRef, 4> ConstraintRefs;
+ SmallVector<Expr *, 4> Exprs;
+ SmallVector<StringRef, 4> ClobberRefs;
+
+ // We need an actual supported target.
+ const llvm::Triple &TheTriple = Actions.Context.getTargetInfo().getTriple();
+ llvm::Triple::ArchType ArchTy = TheTriple.getArch();
+ const std::string &TT = TheTriple.getTriple();
+ const llvm::Target *TheTarget = nullptr;
+ bool UnsupportedArch =
+ (ArchTy != llvm::Triple::x86 && ArchTy != llvm::Triple::x86_64);
+ if (UnsupportedArch) {
+ Diag(AsmLoc, diag::err_msasm_unsupported_arch) << TheTriple.getArchName();
+ } else {
+ std::string Error;
+ TheTarget = llvm::TargetRegistry::lookupTarget(TT, Error);
+ if (!TheTarget)
+ Diag(AsmLoc, diag::err_msasm_unable_to_create_target) << Error;
+ }
+
+ assert(!LBraceLocs.empty() && "Should have at least one location here");
+
+ // If we don't support assembly, or the assembly is empty, we don't
+ // need to instantiate the AsmParser, etc.
+ if (!TheTarget || AsmToks.empty()) {
+ return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, StringRef(),
+ /*NumOutputs*/ 0, /*NumInputs*/ 0,
+ ConstraintRefs, ClobberRefs, Exprs, EndLoc);
+ }
+
+ // Expand the tokens into a string buffer.
+ SmallString<512> AsmString;
+ SmallVector<unsigned, 8> TokOffsets;
+ if (buildMSAsmString(PP, AsmLoc, AsmToks, TokOffsets, AsmString))
+ return StmtError();
+
+ std::unique_ptr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
+ std::unique_ptr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT));
+ // Get the instruction descriptor.
+ std::unique_ptr<llvm::MCInstrInfo> MII(TheTarget->createMCInstrInfo());
+ std::unique_ptr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
+ std::unique_ptr<llvm::MCSubtargetInfo> STI(
+ TheTarget->createMCSubtargetInfo(TT, "", ""));
+
+ llvm::SourceMgr TempSrcMgr;
+ llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr);
+ llvm::MemoryBuffer *Buffer =
+ llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS inline asm>");
+
+ // Tell SrcMgr about this buffer, which is what the parser will pick up.
+ TempSrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc());
+
+ std::unique_ptr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
+ std::unique_ptr<llvm::MCAsmParser> Parser(
+ createMCAsmParser(TempSrcMgr, Ctx, *Str.get(), *MAI));
+
+ // FIXME: init MCOptions from sanitizer flags here.
+ llvm::MCTargetOptions MCOptions;
+ std::unique_ptr<llvm::MCTargetAsmParser> TargetParser(
+ TheTarget->createMCAsmParser(*STI, *Parser, *MII, MCOptions));
+
+ std::unique_ptr<llvm::MCInstPrinter> IP(
+ TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI));
+
+ // Change to the Intel dialect.
+ Parser->setAssemblerDialect(1);
+ Parser->setTargetParser(*TargetParser.get());
+ Parser->setParsingInlineAsm(true);
+ TargetParser->setParsingInlineAsm(true);
+
+ ClangAsmParserCallback Callback(*this, AsmLoc, AsmString, AsmToks,
+ TokOffsets);
+ TargetParser->setSemaCallback(&Callback);
+ TempSrcMgr.setDiagHandler(ClangAsmParserCallback::DiagHandlerCallback,
+ &Callback);
+
+ unsigned NumOutputs;
+ unsigned NumInputs;
+ std::string AsmStringIR;
+ SmallVector<std::pair<void *, bool>, 4> OpExprs;
+ SmallVector<std::string, 4> Constraints;
+ SmallVector<std::string, 4> Clobbers;
+ if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, NumOutputs,
+ NumInputs, OpExprs, Constraints, Clobbers,
+ MII.get(), IP.get(), Callback))
+ return StmtError();
+
+ // Filter out "fpsw". Clang doesn't accept it, and it always lists flags and
+ // fpsr as clobbers.
+ auto End = std::remove(Clobbers.begin(), Clobbers.end(), "fpsw");
+ Clobbers.erase(End, Clobbers.end());
+
+ // Build the vector of clobber StringRefs.
+ ClobberRefs.insert(ClobberRefs.end(), Clobbers.begin(), Clobbers.end());
+
+ // Recast the void pointers and build the vector of constraint StringRefs.
+ unsigned NumExprs = NumOutputs + NumInputs;
+ ConstraintRefs.resize(NumExprs);
+ Exprs.resize(NumExprs);
+ for (unsigned i = 0, e = NumExprs; i != e; ++i) {
+ Expr *OpExpr = static_cast<Expr *>(OpExprs[i].first);
+ if (!OpExpr)
+ return StmtError();
+
+ // Need address of variable.
+ if (OpExprs[i].second)
+ OpExpr =
+ Actions.BuildUnaryOp(getCurScope(), AsmLoc, UO_AddrOf, OpExpr).get();
+
+ ConstraintRefs[i] = StringRef(Constraints[i]);
+ Exprs[i] = OpExpr;
+ }
+
+ // FIXME: We should be passing source locations for better diagnostics.
+ return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, AsmStringIR,
+ NumOutputs, NumInputs, ConstraintRefs,
+ ClobberRefs, Exprs, EndLoc);
+}
+
+/// ParseAsmStatement - Parse a GNU extended asm statement.
+/// asm-statement:
+/// gnu-asm-statement
+/// ms-asm-statement
+///
+/// [GNU] gnu-asm-statement:
+/// 'asm' type-qualifier[opt] '(' asm-argument ')' ';'
+///
+/// [GNU] asm-argument:
+/// asm-string-literal
+/// asm-string-literal ':' asm-operands[opt]
+/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
+/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
+/// ':' asm-clobbers
+///
+/// [GNU] asm-clobbers:
+/// asm-string-literal
+/// asm-clobbers ',' asm-string-literal
+///
+StmtResult Parser::ParseAsmStatement(bool &msAsm) {
+ assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
+ SourceLocation AsmLoc = ConsumeToken();
+
+ if (getLangOpts().AsmBlocks && Tok.isNot(tok::l_paren) &&
+ !isTypeQualifier()) {
+ msAsm = true;
+ return ParseMicrosoftAsmStatement(AsmLoc);
+ }
+ DeclSpec DS(AttrFactory);
+ SourceLocation Loc = Tok.getLocation();
+ ParseTypeQualifierListOpt(DS, true, false);
+
+ // GNU asms accept, but warn, about type-qualifiers other than volatile.
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
+ Diag(Loc, diag::w_asm_qualifier_ignored) << "const";
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
+ Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict";
+ // FIXME: Once GCC supports _Atomic, check whether it permits it here.
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
+ Diag(Loc, diag::w_asm_qualifier_ignored) << "_Atomic";
+
+ // Remember if this was a volatile asm.
+ bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile;
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok, diag::err_expected_lparen_after) << "asm";
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return StmtError();
+ }
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ T.consumeOpen();
+
+ ExprResult AsmString(ParseAsmStringLiteral());
+ if (AsmString.isInvalid()) {
+ // Consume up to and including the closing paren.
+ T.skipToEnd();
+ return StmtError();
+ }
+
+ SmallVector<IdentifierInfo *, 4> Names;
+ ExprVector Constraints;
+ ExprVector Exprs;
+ ExprVector Clobbers;
+
+ if (Tok.is(tok::r_paren)) {
+ // We have a simple asm expression like 'asm("foo")'.
+ T.consumeClose();
+ return Actions.ActOnGCCAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile,
+ /*NumOutputs*/ 0, /*NumInputs*/ 0, nullptr,
+ Constraints, Exprs, AsmString.get(),
+ Clobbers, T.getCloseLocation());
+ }
+
+ // Parse Outputs, if present.
+ bool AteExtraColon = false;
+ if (Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
+ // In C++ mode, parse "::" like ": :".
+ AteExtraColon = Tok.is(tok::coloncolon);
+ ConsumeToken();
+
+ if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs))
+ return StmtError();
+ }
+
+ unsigned NumOutputs = Names.size();
+
+ // Parse Inputs, if present.
+ if (AteExtraColon || Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
+ // In C++ mode, parse "::" like ": :".
+ if (AteExtraColon)
+ AteExtraColon = false;
+ else {
+ AteExtraColon = Tok.is(tok::coloncolon);
+ ConsumeToken();
+ }
+
+ if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs))
+ return StmtError();
+ }
+
+ assert(Names.size() == Constraints.size() &&
+ Constraints.size() == Exprs.size() && "Input operand size mismatch!");
+
+ unsigned NumInputs = Names.size() - NumOutputs;
+
+ // Parse the clobbers, if present.
+ if (AteExtraColon || Tok.is(tok::colon)) {
+ if (!AteExtraColon)
+ ConsumeToken();
+
+ // Parse the asm-string list for clobbers if present.
+ if (Tok.isNot(tok::r_paren)) {
+ while (1) {
+ ExprResult Clobber(ParseAsmStringLiteral());
+
+ if (Clobber.isInvalid())
+ break;
+
+ Clobbers.push_back(Clobber.get());
+
+ if (!TryConsumeToken(tok::comma))
+ break;
+ }
+ }
+ }
+
+ T.consumeClose();
+ return Actions.ActOnGCCAsmStmt(
+ AsmLoc, false, isVolatile, NumOutputs, NumInputs, Names.data(),
+ Constraints, Exprs, AsmString.get(), Clobbers, T.getCloseLocation());
+}
+
+/// ParseAsmOperands - Parse the asm-operands production as used by
+/// asm-statement, assuming the leading ':' token was eaten.
+///
+/// [GNU] asm-operands:
+/// asm-operand
+/// asm-operands ',' asm-operand
+///
+/// [GNU] asm-operand:
+/// asm-string-literal '(' expression ')'
+/// '[' identifier ']' asm-string-literal '(' expression ')'
+///
+//
+// FIXME: Avoid unnecessary std::string trashing.
+bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
+ SmallVectorImpl<Expr *> &Constraints,
+ SmallVectorImpl<Expr *> &Exprs) {
+ // 'asm-operands' isn't present?
+ if (!isTokenStringLiteral() && Tok.isNot(tok::l_square))
+ return false;
+
+ while (1) {
+ // Read the [id] if present.
+ if (Tok.is(tok::l_square)) {
+ BalancedDelimiterTracker T(*this, tok::l_square);
+ T.consumeOpen();
+
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected) << tok::identifier;
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return true;
+ }
+
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ ConsumeToken();
+
+ Names.push_back(II);
+ T.consumeClose();
+ } else
+ Names.push_back(nullptr);
+
+ ExprResult Constraint(ParseAsmStringLiteral());
+ if (Constraint.isInvalid()) {
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return true;
+ }
+ Constraints.push_back(Constraint.get());
+
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok, diag::err_expected_lparen_after) << "asm operand";
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return true;
+ }
+
+ // Read the parenthesized expression.
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ T.consumeOpen();
+ ExprResult Res(ParseExpression());
+ T.consumeClose();
+ if (Res.isInvalid()) {
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return true;
+ }
+ Exprs.push_back(Res.get());
+ // Eat the comma and continue parsing if it exists.
+ if (!TryConsumeToken(tok::comma))
+ return false;
+ }
+}
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 076edb93fa11..fa6401f083a6 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -101,17 +101,13 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
do {
// Consume the 'export', if any.
SourceLocation ExportLoc;
- if (Tok.is(tok::kw_export)) {
- ExportLoc = ConsumeToken();
- }
+ TryConsumeToken(tok::kw_export, ExportLoc);
// Consume the 'template', which should be here.
SourceLocation TemplateLoc;
- if (Tok.is(tok::kw_template)) {
- TemplateLoc = ConsumeToken();
- } else {
+ if (!TryConsumeToken(tok::kw_template, TemplateLoc)) {
Diag(Tok.getLocation(), diag::err_expected_template);
- return 0;
+ return nullptr;
}
// Parse the '<' template-parameter-list '>'
@@ -121,9 +117,8 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
TemplateParams, LAngleLoc, RAngleLoc)) {
// Skip until the semi-colon or a }.
SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
- if (Tok.is(tok::semi))
- ConsumeToken();
- return 0;
+ TryConsumeToken(tok::semi);
+ return nullptr;
}
ParamLists.push_back(
@@ -175,7 +170,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
// We are parsing a member template.
ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo,
&DiagsFromTParams);
- return 0;
+ return nullptr;
}
ParsedAttributesWithRange prefixAttrs(AttrFactory);
@@ -219,7 +214,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
if (Tok.is(tok::semi))
ConsumeToken();
- return 0;
+ return nullptr;
}
LateParsedAttrList LateParsedAttrs(true);
@@ -255,8 +250,8 @@ Parser::ParseSingleDeclarationAfterTemplate(
// Recover as if it were an explicit specialization.
TemplateParameterLists FakedParamLists;
FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
- 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, 0, 0,
- LAngleLoc));
+ 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, nullptr,
+ 0, LAngleLoc));
return ParseFunctionDefinition(
DeclaratorInfo, ParsedTemplateInfo(&FakedParamLists,
@@ -302,11 +297,10 @@ bool Parser::ParseTemplateParameters(unsigned Depth,
SourceLocation &LAngleLoc,
SourceLocation &RAngleLoc) {
// Get the template parameter list.
- if (!Tok.is(tok::less)) {
+ if (!TryConsumeToken(tok::less, LAngleLoc)) {
Diag(Tok.getLocation(), diag::err_expected_less_after) << "template";
return true;
}
- LAngleLoc = ConsumeToken();
// Try to parse the template parameter list.
bool Failed = false;
@@ -322,10 +316,8 @@ bool Parser::ParseTemplateParameters(unsigned Depth,
Tok.setKind(tok::greater);
RAngleLoc = Tok.getLocation();
Tok.setLocation(Tok.getLocation().getLocWithOffset(1));
- } else if (Tok.is(tok::greater))
- RAngleLoc = ConsumeToken();
- else if (Failed) {
- Diag(Tok.getLocation(), diag::err_expected_greater);
+ } else if (!TryConsumeToken(tok::greater, RAngleLoc) && Failed) {
+ Diag(Tok.getLocation(), diag::err_expected) << tok::greater;
return true;
}
return false;
@@ -481,12 +473,8 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
SourceLocation KeyLoc = ConsumeToken();
// Grab the ellipsis (if given).
- bool Ellipsis = false;
SourceLocation EllipsisLoc;
- if (Tok.is(tok::ellipsis)) {
- Ellipsis = true;
- EllipsisLoc = ConsumeToken();
-
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) {
Diag(EllipsisLoc,
getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_variadic_templates
@@ -495,7 +483,7 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
// Grab the template parameter name (if given)
SourceLocation NameLoc;
- IdentifierInfo* ParamName = 0;
+ IdentifierInfo *ParamName = nullptr;
if (Tok.is(tok::identifier)) {
ParamName = Tok.getIdentifierInfo();
NameLoc = ConsumeToken();
@@ -504,34 +492,40 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
// Unnamed template parameter. Don't have to do anything here, just
// don't consume this token.
} else {
- Diag(Tok.getLocation(), diag::err_expected_ident);
- return 0;
+ Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
+ return nullptr;
}
+ // Recover from misplaced ellipsis.
+ bool AlreadyHasEllipsis = EllipsisLoc.isValid();
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
+ DiagnoseMisplacedEllipsis(EllipsisLoc, NameLoc, AlreadyHasEllipsis, true);
+
// Grab a default argument (if available).
// Per C++0x [basic.scope.pdecl]p9, we parse the default argument before
// we introduce the type parameter into the local scope.
SourceLocation EqualLoc;
ParsedType DefaultArg;
- if (Tok.is(tok::equal)) {
- EqualLoc = ConsumeToken();
- DefaultArg = ParseTypeName(/*Range=*/0,
+ if (TryConsumeToken(tok::equal, EqualLoc))
+ DefaultArg = ParseTypeName(/*Range=*/nullptr,
Declarator::TemplateTypeArgContext).get();
- }
- return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, Ellipsis,
- EllipsisLoc, KeyLoc, ParamName, NameLoc,
- Depth, Position, EqualLoc, DefaultArg);
+ return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, EllipsisLoc,
+ KeyLoc, ParamName, NameLoc, Depth, Position,
+ EqualLoc, DefaultArg);
}
/// ParseTemplateTemplateParameter - Handle the parsing of template
/// template parameters.
///
/// type-parameter: [C++ temp.param]
-/// 'template' '<' template-parameter-list '>' 'class'
+/// 'template' '<' template-parameter-list '>' type-parameter-key
/// ...[opt] identifier[opt]
-/// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
-/// = id-expression
+/// 'template' '<' template-parameter-list '>' type-parameter-key
+/// identifier[opt] = id-expression
+/// type-parameter-key:
+/// 'class'
+/// 'typename' [C++1z]
Decl *
Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
assert(Tok.is(tok::kw_template) && "Expected 'template' keyword");
@@ -544,45 +538,50 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
if (ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc,
RAngleLoc)) {
- return 0;
+ return nullptr;
}
}
+ // Provide an ExtWarn if the C++1z feature of using 'typename' here is used.
// Generate a meaningful error if the user forgot to put class before the
// identifier, comma, or greater. Provide a fixit if the identifier, comma,
- // or greater appear immediately or after 'typename' or 'struct'. In the
- // latter case, replace the keyword with 'class'.
- if (!Tok.is(tok::kw_class)) {
+ // 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);
- const Token& Next = Replace ? NextToken() : Tok;
- if (Next.is(tok::identifier) || Next.is(tok::comma) ||
- Next.is(tok::greater) || Next.is(tok::greatergreater) ||
- Next.is(tok::ellipsis))
+ const Token &Next = Tok.is(tok::kw_struct) ? NextToken() : Tok;
+ if (Tok.is(tok::kw_typename)) {
+ Diag(Tok.getLocation(),
+ getLangOpts().CPlusPlus1z
+ ? diag::warn_cxx1y_compat_template_template_param_typename
+ : diag::ext_template_template_param_typename)
+ << (!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)) {
Diag(Tok.getLocation(), diag::err_class_on_template_template_param)
<< (Replace ? FixItHint::CreateReplacement(Tok.getLocation(), "class")
: FixItHint::CreateInsertion(Tok.getLocation(), "class "));
- else
+ } else
Diag(Tok.getLocation(), diag::err_class_on_template_template_param);
if (Replace)
ConsumeToken();
- } else
- ConsumeToken();
+ }
// Parse the ellipsis, if given.
SourceLocation EllipsisLoc;
- if (Tok.is(tok::ellipsis)) {
- EllipsisLoc = ConsumeToken();
-
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
Diag(EllipsisLoc,
getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_variadic_templates
: diag::ext_variadic_templates);
- }
// Get the identifier, if given.
SourceLocation NameLoc;
- IdentifierInfo* ParamName = 0;
+ IdentifierInfo *ParamName = nullptr;
if (Tok.is(tok::identifier)) {
ParamName = Tok.getIdentifierInfo();
NameLoc = ConsumeToken();
@@ -591,10 +590,15 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
// Unnamed template parameter. Don't have to do anything here, just
// don't consume this token.
} else {
- Diag(Tok.getLocation(), diag::err_expected_ident);
- return 0;
+ Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
+ return nullptr;
}
+ // Recover from misplaced ellipsis.
+ bool AlreadyHasEllipsis = EllipsisLoc.isValid();
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
+ DiagnoseMisplacedEllipsis(EllipsisLoc, NameLoc, AlreadyHasEllipsis, true);
+
TemplateParameterList *ParamList =
Actions.ActOnTemplateParameterList(Depth, SourceLocation(),
TemplateLoc, LAngleLoc,
@@ -607,8 +611,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
// we introduce the template parameter into the local scope.
SourceLocation EqualLoc;
ParsedTemplateArgument DefaultArg;
- if (Tok.is(tok::equal)) {
- EqualLoc = ConsumeToken();
+ if (TryConsumeToken(tok::equal, EqualLoc)) {
DefaultArg = ParseTemplateTemplateArgument();
if (DefaultArg.isInvalid()) {
Diag(Tok.getLocation(),
@@ -643,17 +646,20 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
ParseDeclarator(ParamDecl);
if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {
Diag(Tok.getLocation(), diag::err_expected_template_parameter);
- return 0;
+ return nullptr;
}
+ // Recover from misplaced ellipsis.
+ SourceLocation EllipsisLoc;
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
+ DiagnoseMisplacedEllipsisInDeclarator(EllipsisLoc, ParamDecl);
+
// If there is a default value, parse it.
// Per C++0x [basic.scope.pdecl]p9, we parse the default argument before
// we introduce the template parameter into the local scope.
SourceLocation EqualLoc;
ExprResult DefaultArg;
- if (Tok.is(tok::equal)) {
- EqualLoc = ConsumeToken();
-
+ if (TryConsumeToken(tok::equal, EqualLoc)) {
// C++ [temp.param]p15:
// When parsing a default template-argument for a non-type
// template-parameter, the first non-nested > is taken as the
@@ -670,7 +676,29 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
// Create the parameter.
return Actions.ActOnNonTypeTemplateParameter(getCurScope(), ParamDecl,
Depth, Position, EqualLoc,
- DefaultArg.take());
+ DefaultArg.get());
+}
+
+void Parser::DiagnoseMisplacedEllipsis(SourceLocation EllipsisLoc,
+ SourceLocation CorrectLoc,
+ bool AlreadyHasEllipsis,
+ bool IdentifierHasName) {
+ FixItHint Insertion;
+ if (!AlreadyHasEllipsis)
+ Insertion = FixItHint::CreateInsertion(CorrectLoc, "...");
+ Diag(EllipsisLoc, diag::err_misplaced_ellipsis_in_declaration)
+ << FixItHint::CreateRemoval(EllipsisLoc) << Insertion
+ << !IdentifierHasName;
+}
+
+void Parser::DiagnoseMisplacedEllipsisInDeclarator(SourceLocation EllipsisLoc,
+ Declarator &D) {
+ assert(EllipsisLoc.isValid());
+ bool AlreadyHasEllipsis = D.getEllipsisLoc().isValid();
+ if (!AlreadyHasEllipsis)
+ D.setEllipsisLoc(EllipsisLoc);
+ DiagnoseMisplacedEllipsis(EllipsisLoc, D.getIdentifierLoc(),
+ AlreadyHasEllipsis, D.hasName());
}
/// \brief Parses a '>' at the end of a template list.
@@ -692,7 +720,7 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
switch (Tok.getKind()) {
default:
- Diag(Tok.getLocation(), diag::err_expected_greater);
+ Diag(Tok.getLocation(), diag::err_expected) << tok::greater;
return true;
case tok::greater:
@@ -723,7 +751,9 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
// This template-id is terminated by a token which starts with a '>'. Outside
// C++11, this is now error recovery, and in C++11, this is error recovery if
- // the token isn't '>>'.
+ // the token isn't '>>' or '>>>'.
+ // '>>>' is for CUDA, where this sequence of characters is parsed into
+ // tok::greatergreatergreater, rather than two separate tokens.
RAngleLoc = Tok.getLocation();
@@ -753,7 +783,8 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " ");
unsigned DiagId = diag::err_two_right_angle_brackets_need_space;
- if (getLangOpts().CPlusPlus11 && Tok.is(tok::greatergreater))
+ if (getLangOpts().CPlusPlus11 &&
+ (Tok.is(tok::greatergreater) || Tok.is(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;
@@ -900,8 +931,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
if (Invalid) {
// If we failed to parse the template ID but skipped ahead to a >, we're not
// going to be able to form a token annotation. Eat the '>' if present.
- if (Tok.is(tok::greater))
- ConsumeToken();
+ TryConsumeToken(tok::greater);
return true;
}
@@ -916,8 +946,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
if (Type.isInvalid()) {
// If we failed to parse the template ID but skipped ahead to a >, we're not
// going to be able to form a token annotation. Eat the '>' if present.
- if (Tok.is(tok::greater))
- ConsumeToken();
+ TryConsumeToken(tok::greater);
return true;
}
@@ -940,7 +969,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
TemplateId->Name = TemplateName.Identifier;
TemplateId->Operator = OO_None;
} else {
- TemplateId->Name = 0;
+ TemplateId->Name = nullptr;
TemplateId->Operator = TemplateName.OperatorFunctionId.Operator;
}
TemplateId->SS = SS;
@@ -1044,11 +1073,9 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
UnqualifiedId Name;
Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
ConsumeToken(); // the identifier
-
- // Parse the ellipsis.
- if (Tok.is(tok::ellipsis))
- EllipsisLoc = ConsumeToken();
-
+
+ TryConsumeToken(tok::ellipsis, EllipsisLoc);
+
// If the next token signals the end of a template argument,
// then we have a dependent template name that could be a template
// template argument.
@@ -1067,10 +1094,8 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
UnqualifiedId Name;
Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
ConsumeToken(); // the identifier
-
- // Parse the ellipsis.
- if (Tok.is(tok::ellipsis))
- EllipsisLoc = ConsumeToken();
+
+ TryConsumeToken(tok::ellipsis, EllipsisLoc);
if (isEndOfTemplateArgument(Tok)) {
bool MemberOfUnknownSpecialization;
@@ -1111,7 +1136,7 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() {
// Therefore, we initially try to parse a type-id.
if (isCXXTypeId(TypeIdAsTemplateArgument)) {
SourceLocation Loc = Tok.getLocation();
- TypeResult TypeArg = ParseTypeName(/*Range=*/0,
+ TypeResult TypeArg = ParseTypeName(/*Range=*/nullptr,
Declarator::TemplateTypeArgContext);
if (TypeArg.isInvalid())
return ParsedTemplateArgument();
@@ -1143,7 +1168,7 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() {
return ParsedTemplateArgument();
return ParsedTemplateArgument(ParsedTemplateArgument::NonType,
- ExprArg.release(), Loc);
+ ExprArg.get(), Loc);
}
/// \brief Determine whether the current tokens can only be parsed as a
@@ -1161,16 +1186,15 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) {
}
// '<'
- if (!Tok.is(tok::less))
+ if (!TryConsumeToken(tok::less))
return false;
- ConsumeToken();
// An empty template argument list.
if (Tok.is(tok::greater))
return true;
// See whether we have declaration specifiers, which indicate a type.
- while (isCXXDeclarationSpecifier() == TPResult::True())
+ while (isCXXDeclarationSpecifier() == TPResult::True)
ConsumeToken();
// If we have a '>' or a ',' then this is a template argument list.
@@ -1187,13 +1211,13 @@ bool
Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
// Template argument lists are constant-evaluation contexts.
EnterExpressionEvaluationContext EvalContext(Actions,Sema::ConstantEvaluated);
+ ColonProtectionRAIIObject ColonProtection(*this, false);
- while (true) {
+ do {
ParsedTemplateArgument Arg = ParseTemplateArgument();
- if (Tok.is(tok::ellipsis)) {
- SourceLocation EllipsisLoc = ConsumeToken();
+ SourceLocation EllipsisLoc;
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
Arg = Actions.ActOnPackExpansion(Arg, EllipsisLoc);
- }
if (Arg.isInvalid()) {
SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch);
@@ -1205,11 +1229,7 @@ Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
// If the next token is a comma, consume it and keep reading
// arguments.
- if (Tok.isNot(tok::comma)) break;
-
- // Consume the comma.
- ConsumeToken();
- }
+ } while (TryConsumeToken(tok::comma));
return false;
}
@@ -1258,9 +1278,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
return;
// Get the FunctionDecl.
- FunctionTemplateDecl *FunTmplD = dyn_cast<FunctionTemplateDecl>(LPT.D);
- FunctionDecl *FunD =
- FunTmplD ? FunTmplD->getTemplatedDecl() : cast<FunctionDecl>(LPT.D);
+ FunctionDecl *FunD = LPT.D->getAsFunction();
// Track template parameter depth.
TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
@@ -1271,7 +1289,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
// Get the list of DeclContexts to reenter.
SmallVector<DeclContext*, 4> DeclContextsToReenter;
- DeclContext *DD = FunD->getLexicalParent();
+ DeclContext *DD = FunD;
while (DD && !DD->isTranslationUnit()) {
DeclContextsToReenter.push_back(DD);
DD = DD->getLexicalParent();
@@ -1281,35 +1299,16 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
SmallVectorImpl<DeclContext *>::reverse_iterator II =
DeclContextsToReenter.rbegin();
for (; II != DeclContextsToReenter.rend(); ++II) {
- if (ClassTemplatePartialSpecializationDecl *MD =
- dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(*II)) {
- TemplateParamScopeStack.push_back(
- new ParseScope(this, Scope::TemplateParamScope));
- Actions.ActOnReenterTemplateScope(getCurScope(), MD);
- ++CurTemplateDepthTracker;
- } else if (CXXRecordDecl *MD = dyn_cast_or_null<CXXRecordDecl>(*II)) {
- bool IsClassTemplate = MD->getDescribedClassTemplate() != 0;
- TemplateParamScopeStack.push_back(
- new ParseScope(this, Scope::TemplateParamScope,
- /*ManageScope*/IsClassTemplate));
- Actions.ActOnReenterTemplateScope(getCurScope(),
- MD->getDescribedClassTemplate());
- if (IsClassTemplate)
- ++CurTemplateDepthTracker;
+ TemplateParamScopeStack.push_back(new ParseScope(this,
+ Scope::TemplateParamScope));
+ unsigned NumParamLists =
+ Actions.ActOnReenterTemplateScope(getCurScope(), cast<Decl>(*II));
+ CurTemplateDepthTracker.addDepth(NumParamLists);
+ if (*II != FunD) {
+ TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope));
+ Actions.PushDeclContext(Actions.getCurScope(), *II);
}
- TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope));
- Actions.PushDeclContext(Actions.getCurScope(), *II);
- }
- TemplateParamScopeStack.push_back(
- new ParseScope(this, Scope::TemplateParamScope));
-
- DeclaratorDecl *Declarator = dyn_cast<DeclaratorDecl>(FunD);
- if (Declarator && Declarator->getNumTemplateParameterLists() != 0) {
- Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator);
- ++CurTemplateDepthTracker;
}
- Actions.ActOnReenterTemplateScope(getCurScope(), LPT.D);
- ++CurTemplateDepthTracker;
assert(!LPT.Toks.empty() && "Empty body!");
@@ -1341,14 +1340,16 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
Actions.ActOnDefaultCtorInitializers(LPT.D);
if (Tok.is(tok::l_brace)) {
- assert((!FunTmplD || FunTmplD->getTemplateParameters()->getDepth() <
- TemplateParameterDepth) &&
+ assert((!isa<FunctionTemplateDecl>(LPT.D) ||
+ cast<FunctionTemplateDecl>(LPT.D)
+ ->getTemplateParameters()
+ ->getDepth() == TemplateParameterDepth - 1) &&
"TemplateParameterDepth should be greater than the depth of "
"current template being instantiated!");
ParseFunctionStatementBody(LPT.D, FnScope);
Actions.UnmarkAsLateParsedTemplate(FunD);
} else
- Actions.ActOnFinishFunctionBody(LPT.D, 0);
+ Actions.ActOnFinishFunctionBody(LPT.D, nullptr);
}
// Exit scopes.
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index a1d6b13fdab8..8514af2a8c89 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -101,15 +101,15 @@ bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) {
// an ambiguity if the first decl-specifier is
// simple-type-specifier/typename-specifier followed by a '(', which may
// indicate a function-style cast expression.
- // isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such
+ // isCXXDeclarationSpecifier will return TPResult::Ambiguous only in such
// a case.
bool InvalidAsDeclaration = false;
- TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(),
+ TPResult TPR = isCXXDeclarationSpecifier(TPResult::False,
&InvalidAsDeclaration);
- if (TPR != TPResult::Ambiguous())
- return TPR != TPResult::False(); // Returns true for TPResult::True() or
- // TPResult::Error().
+ if (TPR != TPResult::Ambiguous)
+ return TPR != TPResult::False; // Returns true for TPResult::True or
+ // TPResult::Error.
// FIXME: TryParseSimpleDeclaration doesn't look past the first initializer,
// and so gets some cases wrong. We can't carry on if we've already seen
@@ -131,15 +131,15 @@ bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) {
PA.Revert();
// In case of an error, let the declaration parsing code handle it.
- if (TPR == TPResult::Error())
+ if (TPR == TPResult::Error)
return true;
// Declarations take precedence over expressions.
- if (TPR == TPResult::Ambiguous())
- TPR = TPResult::True();
+ if (TPR == TPResult::Ambiguous)
+ TPR = TPResult::True;
- assert(TPR == TPResult::True() || TPR == TPResult::False());
- return TPR == TPResult::True();
+ assert(TPR == TPResult::True || TPR == TPResult::False);
+ return TPR == TPResult::True;
}
/// Try to consume a token sequence that we've already identified as
@@ -157,10 +157,10 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
case tok::kw___underlying_type: {
ConsumeToken();
if (Tok.isNot(tok::l_paren))
- return TPResult::Error();
+ return TPResult::Error;
ConsumeParen();
if (!SkipUntil(tok::r_paren))
- return TPResult::Error();
+ return TPResult::Error;
break;
}
@@ -184,23 +184,23 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
if (Tok.is(tok::l_square)) {
ConsumeBracket();
if (!SkipUntil(tok::r_square))
- return TPResult::Error();
+ return TPResult::Error;
} else {
ConsumeToken();
if (Tok.isNot(tok::l_paren))
- return TPResult::Error();
+ return TPResult::Error;
ConsumeParen();
if (!SkipUntil(tok::r_paren))
- return TPResult::Error();
+ return TPResult::Error;
}
}
if (TryAnnotateCXXScopeToken())
- return TPResult::Error();
+ return TPResult::Error;
if (Tok.is(tok::annot_cxxscope))
ConsumeToken();
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
- return TPResult::Error();
+ return TPResult::Error;
ConsumeToken();
break;
@@ -215,7 +215,7 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
break;
}
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
/// simple-declaration:
@@ -227,29 +227,29 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
/// attribute-specifier-seqopt type-specifier-seq declarator
///
Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {
- if (TryConsumeDeclarationSpecifier() == TPResult::Error())
- return TPResult::Error();
+ if (TryConsumeDeclarationSpecifier() == TPResult::Error)
+ return TPResult::Error;
// Two decl-specifiers in a row conclusively disambiguate this as being a
// simple-declaration. Don't bother calling isCXXDeclarationSpecifier in the
// overwhelmingly common case that the next token is a '('.
if (Tok.isNot(tok::l_paren)) {
TPResult TPR = isCXXDeclarationSpecifier();
- if (TPR == TPResult::Ambiguous())
- return TPResult::True();
- if (TPR == TPResult::True() || TPR == TPResult::Error())
+ if (TPR == TPResult::Ambiguous)
+ return TPResult::True;
+ if (TPR == TPResult::True || TPR == TPResult::Error)
return TPR;
- assert(TPR == TPResult::False());
+ assert(TPR == TPResult::False);
}
TPResult TPR = TryParseInitDeclaratorList();
- if (TPR != TPResult::Ambiguous())
+ if (TPR != TPResult::Ambiguous)
return TPR;
if (Tok.isNot(tok::semi) && (!AllowForRangeDecl || Tok.isNot(tok::colon)))
- return TPResult::False();
+ return TPResult::False;
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
/// Tentatively parse an init-declarator-list in order to disambiguate it from
@@ -283,23 +283,23 @@ Parser::TPResult Parser::TryParseInitDeclaratorList() {
while (1) {
// declarator
TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/);
- if (TPR != TPResult::Ambiguous())
+ if (TPR != TPResult::Ambiguous)
return TPR;
// [GNU] simple-asm-expr[opt] attributes[opt]
if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
- return TPResult::True();
+ return TPResult::True;
// initializer[opt]
if (Tok.is(tok::l_paren)) {
// Parse through the parens.
ConsumeParen();
if (!SkipUntil(tok::r_paren, StopAtSemi))
- return TPResult::Error();
+ return TPResult::Error;
} else if (Tok.is(tok::l_brace)) {
// A left-brace here is sufficient to disambiguate the parse; an
// expression can never be followed directly by a braced-init-list.
- return TPResult::True();
+ return TPResult::True;
} else if (Tok.is(tok::equal) || isTokIdentifier_in()) {
// MSVC and g++ won't examine the rest of declarators if '=' is
// encountered; they just conclude that we have a declaration.
@@ -317,15 +317,14 @@ Parser::TPResult Parser::TryParseInitDeclaratorList() {
// in any other context 'in' is invalid after a declaration and parser
// issues the error regardless of outcome of this decision.
// FIXME: Change if above assumption does not hold.
- return TPResult::True();
+ return TPResult::True;
}
- if (Tok.isNot(tok::comma))
+ if (!TryConsumeToken(tok::comma))
break;
- ConsumeToken(); // the comma.
}
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
/// isCXXConditionDeclaration - Disambiguates between a declaration or an
@@ -343,9 +342,9 @@ Parser::TPResult Parser::TryParseInitDeclaratorList() {
///
bool Parser::isCXXConditionDeclaration() {
TPResult TPR = isCXXDeclarationSpecifier();
- if (TPR != TPResult::Ambiguous())
- return TPR != TPResult::False(); // Returns true for TPResult::True() or
- // TPResult::Error().
+ if (TPR != TPResult::Ambiguous)
+ return TPR != TPResult::False; // Returns true for TPResult::True or
+ // TPResult::Error.
// FIXME: Add statistics about the number of ambiguous statements encountered
// and how they were resolved (number of declarations+number of expressions).
@@ -363,25 +362,25 @@ bool Parser::isCXXConditionDeclaration() {
TPR = TryParseDeclarator(false/*mayBeAbstract*/);
// In case of an error, let the declaration parsing code handle it.
- if (TPR == TPResult::Error())
- TPR = TPResult::True();
+ if (TPR == TPResult::Error)
+ TPR = TPResult::True;
- if (TPR == TPResult::Ambiguous()) {
+ 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))
- TPR = TPResult::True();
+ TPR = TPResult::True;
else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace))
- TPR = TPResult::True();
+ TPR = TPResult::True;
else
- TPR = TPResult::False();
+ TPR = TPResult::False;
}
PA.Revert();
- assert(TPR == TPResult::True() || TPR == TPResult::False());
- return TPR == TPResult::True();
+ assert(TPR == TPResult::True || TPR == TPResult::False);
+ return TPR == TPResult::True;
}
/// \brief Determine whether the next set of tokens contains a type-id.
@@ -413,9 +412,9 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
// in its syntactic context shall be considered a type-id.
TPResult TPR = isCXXDeclarationSpecifier();
- if (TPR != TPResult::Ambiguous())
- return TPR != TPResult::False(); // Returns true for TPResult::True() or
- // TPResult::Error().
+ if (TPR != TPResult::Ambiguous)
+ return TPR != TPResult::False; // Returns true for TPResult::True or
+ // TPResult::Error.
// FIXME: Add statistics about the number of ambiguous statements encountered
// and how they were resolved (number of declarations+number of expressions).
@@ -433,14 +432,14 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/);
// In case of an error, let the declaration parsing code handle it.
- if (TPR == TPResult::Error())
- TPR = TPResult::True();
+ if (TPR == TPResult::Error)
+ TPR = TPResult::True;
- if (TPR == TPResult::Ambiguous()) {
+ if (TPR == TPResult::Ambiguous) {
// We are supposed to be inside parens, so if after the abstract declarator
// we encounter a ')' this is a type-id, otherwise it's an expression.
if (Context == TypeIdInParens && Tok.is(tok::r_paren)) {
- TPR = TPResult::True();
+ TPR = TPResult::True;
isAmbiguous = true;
// We are supposed to be inside a template argument, so if after
@@ -449,17 +448,17 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
} else if (Context == TypeIdAsTemplateArgument &&
(Tok.is(tok::greater) || Tok.is(tok::comma) ||
(getLangOpts().CPlusPlus11 && Tok.is(tok::greatergreater)))) {
- TPR = TPResult::True();
+ TPR = TPResult::True;
isAmbiguous = true;
} else
- TPR = TPResult::False();
+ TPR = TPResult::False;
}
PA.Revert();
- assert(TPR == TPResult::True() || TPR == TPResult::False());
- return TPR == TPResult::True();
+ assert(TPR == TPResult::True || TPR == TPResult::False);
+ return TPR == TPResult::True;
}
/// \brief Returns true if this is a C++11 attribute-specifier. Per
@@ -595,13 +594,10 @@ Parser::isCXX11AttributeSpecifier(bool Disambiguate,
}
}
- if (Tok.is(tok::ellipsis))
- ConsumeToken();
+ TryConsumeToken(tok::ellipsis);
- if (Tok.isNot(tok::comma))
+ if (!TryConsumeToken(tok::comma))
break;
-
- ConsumeToken();
}
// An attribute must end ']]'.
@@ -628,7 +624,7 @@ Parser::TPResult Parser::TryParsePtrOperatorSeq() {
while (true) {
if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier))
if (TryAnnotateCXXScopeToken(true))
- return TPResult::Error();
+ return TPResult::Error;
if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) ||
Tok.is(tok::ampamp) ||
@@ -640,7 +636,7 @@ Parser::TPResult Parser::TryParsePtrOperatorSeq() {
Tok.is(tok::kw_restrict))
ConsumeToken();
} else {
- return TPResult::True();
+ return TPResult::True;
}
}
}
@@ -675,20 +671,20 @@ Parser::TPResult Parser::TryParseOperatorId() {
ConsumeBracket();
ConsumeBracket();
}
- return TPResult::True();
+ return TPResult::True;
#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemOnly) \
case tok::Token:
#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemOnly)
#include "clang/Basic/OperatorKinds.def"
ConsumeToken();
- return TPResult::True();
+ return TPResult::True;
case tok::l_square:
if (NextToken().is(tok::r_square)) {
ConsumeBracket();
ConsumeBracket();
- return TPResult::True();
+ return TPResult::True;
}
break;
@@ -696,7 +692,7 @@ Parser::TPResult Parser::TryParseOperatorId() {
if (NextToken().is(tok::r_paren)) {
ConsumeParen();
ConsumeParen();
- return TPResult::True();
+ return TPResult::True;
}
break;
@@ -716,24 +712,24 @@ Parser::TPResult Parser::TryParseOperatorId() {
if (Tok.is(tok::identifier))
ConsumeToken();
else
- return TPResult::Error();
+ return TPResult::Error;
}
- return TPResult::True();
+ return TPResult::True;
}
// Maybe this is a conversion-function-id.
bool AnyDeclSpecifiers = false;
while (true) {
TPResult TPR = isCXXDeclarationSpecifier();
- if (TPR == TPResult::Error())
+ if (TPR == TPResult::Error)
return TPR;
- if (TPR == TPResult::False()) {
+ if (TPR == TPResult::False) {
if (!AnyDeclSpecifiers)
- return TPResult::Error();
+ return TPResult::Error;
break;
}
- if (TryConsumeDeclarationSpecifier() == TPResult::Error())
- return TPResult::Error();
+ if (TryConsumeDeclarationSpecifier() == TPResult::Error)
+ return TPResult::Error;
AnyDeclSpecifiers = true;
}
return TryParsePtrOperatorSeq();
@@ -797,8 +793,8 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
// declarator:
// direct-declarator
// ptr-operator declarator
- if (TryParsePtrOperatorSeq() == TPResult::Error())
- return TPResult::Error();
+ if (TryParsePtrOperatorSeq() == TPResult::Error)
+ return TPResult::Error;
// direct-declarator:
// direct-abstract-declarator:
@@ -815,8 +811,8 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
else if (Tok.is(tok::identifier))
TentativelyDeclaredIdentifiers.push_back(Tok.getIdentifierInfo());
if (Tok.is(tok::kw_operator)) {
- if (TryParseOperatorId() == TPResult::Error())
- return TPResult::Error();
+ if (TryParseOperatorId() == TPResult::Error)
+ return TPResult::Error;
} else
ConsumeToken();
} else if (Tok.is(tok::l_paren)) {
@@ -829,7 +825,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
// exception-specification[opt]
TPResult TPR = TryParseFunctionDeclarator();
- if (TPR != TPResult::Ambiguous())
+ if (TPR != TPResult::Ambiguous)
return TPR;
} else {
// '(' declarator ')'
@@ -842,20 +838,20 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
Tok.is(tok::kw___fastcall) ||
Tok.is(tok::kw___thiscall) ||
Tok.is(tok::kw___unaligned))
- return TPResult::True(); // attributes indicate declaration
+ return TPResult::True; // attributes indicate declaration
TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);
- if (TPR != TPResult::Ambiguous())
+ if (TPR != TPResult::Ambiguous)
return TPR;
if (Tok.isNot(tok::r_paren))
- return TPResult::False();
+ return TPResult::False;
ConsumeParen();
}
} else if (!mayBeAbstract) {
- return TPResult::False();
+ return TPResult::False;
}
while (1) {
- TPResult TPR(TPResult::Ambiguous());
+ TPResult TPR(TPResult::Ambiguous);
// abstract-declarator: ...
if (Tok.is(tok::ellipsis))
@@ -881,11 +877,11 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
break;
}
- if (TPR != TPResult::Ambiguous())
+ if (TPR != TPResult::Ambiguous)
return TPR;
}
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
Parser::TPResult
@@ -935,42 +931,19 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
case tok::kw___alignof:
case tok::kw___builtin_choose_expr:
case tok::kw___builtin_offsetof:
- case tok::kw___builtin_types_compatible_p:
case tok::kw___builtin_va_arg:
case tok::kw___imag:
case tok::kw___real:
case tok::kw___FUNCTION__:
case tok::kw___FUNCDNAME__:
+ case tok::kw___FUNCSIG__:
case tok::kw_L__FUNCTION__:
case tok::kw___PRETTY_FUNCTION__:
- case tok::kw___has_nothrow_assign:
- case tok::kw___has_nothrow_copy:
- case tok::kw___has_nothrow_constructor:
- case tok::kw___has_trivial_assign:
- case tok::kw___has_trivial_copy:
- case tok::kw___has_trivial_constructor:
- case tok::kw___has_trivial_destructor:
- case tok::kw___has_virtual_destructor:
- case tok::kw___is_abstract:
- case tok::kw___is_base_of:
- case tok::kw___is_class:
- case tok::kw___is_convertible_to:
- case tok::kw___is_empty:
- case tok::kw___is_enum:
- case tok::kw___is_interface_class:
- case tok::kw___is_final:
- case tok::kw___is_literal:
- case tok::kw___is_literal_type:
- case tok::kw___is_pod:
- case tok::kw___is_polymorphic:
- case tok::kw___is_sealed:
- case tok::kw___is_trivial:
- case tok::kw___is_trivially_assignable:
- case tok::kw___is_trivially_constructible:
- case tok::kw___is_trivially_copyable:
- case tok::kw___is_union:
case tok::kw___uuidof:
- return TPResult::True();
+#define TYPE_TRAIT(N,Spelling,K) \
+ case tok::kw_##Spelling:
+#include "clang/Basic/TokenKinds.def"
+ return TPResult::True;
// Obviously starts a type-specifier-seq:
case tok::kw_char:
@@ -1015,22 +988,14 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
case tok::kw___vector:
case tok::kw___pixel:
case tok::kw__Atomic:
- case tok::kw_image1d_t:
- case tok::kw_image1d_array_t:
- case tok::kw_image1d_buffer_t:
- case tok::kw_image2d_t:
- case tok::kw_image2d_array_t:
- case tok::kw_image3d_t:
- case tok::kw_sampler_t:
- case tok::kw_event_t:
case tok::kw___unknown_anytype:
- return TPResult::False();
+ return TPResult::False;
default:
break;
}
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
bool Parser::isTentativelyDeclared(IdentifierInfo *II) {
@@ -1039,16 +1004,16 @@ bool Parser::isTentativelyDeclared(IdentifierInfo *II) {
!= TentativelyDeclaredIdentifiers.end();
}
-/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration
-/// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could
-/// be either a decl-specifier or a function-style cast, and TPResult::Error()
+/// isCXXDeclarationSpecifier - Returns TPResult::True if it is a declaration
+/// specifier, TPResult::False if it is not, TPResult::Ambiguous if it could
+/// be either a decl-specifier or a function-style cast, and TPResult::Error
/// if a parsing error was found and reported.
///
/// If HasMissingTypename is provided, a name with a dependent scope specifier
/// will be treated as ambiguous if the 'typename' keyword is missing. If this
/// happens, *HasMissingTypename will be set to 'true'. This will also be used
/// as an indicator that undeclared identifiers (which will trigger a later
-/// parse error) should be treated as types. Returns TPResult::Ambiguous() in
+/// parse error) should be treated as types. Returns TPResult::Ambiguous in
/// such cases.
///
/// decl-specifier:
@@ -1152,12 +1117,12 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
// Check for need to substitute AltiVec __vector keyword
// for "vector" identifier.
if (TryAltiVecVectorToken())
- return TPResult::True();
+ return TPResult::True;
const Token &Next = NextToken();
// In 'foo bar', 'foo' is always a type name outside of Objective-C.
if (!getLangOpts().ObjC1 && Next.is(tok::identifier))
- return TPResult::True();
+ return TPResult::True;
if (Next.isNot(tok::coloncolon) && Next.isNot(tok::less)) {
// Determine whether this is a valid expression. If not, we will hit
@@ -1170,15 +1135,15 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
switch (TryAnnotateName(false /* no nested name specifier */,
&TypoCorrection)) {
case ANK_Error:
- return TPResult::Error();
+ return TPResult::Error;
case ANK_TentativeDecl:
- return TPResult::False();
+ return TPResult::False;
case ANK_TemplateName:
// A bare type template-name which can't be a template template
// argument is an error, and was probably intended to be a type.
- return GreaterThanIsOperator ? TPResult::True() : TPResult::False();
+ return GreaterThanIsOperator ? TPResult::True : TPResult::False;
case ANK_Unresolved:
- return HasMissingTypename ? TPResult::Ambiguous() : TPResult::False();
+ return HasMissingTypename ? TPResult::Ambiguous : TPResult::False;
case ANK_Success:
break;
}
@@ -1190,12 +1155,12 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
// since it will annotate as a primary expression, and we want to use the
// "missing 'typename'" logic.
if (TryAnnotateTypeOrScopeToken())
- return TPResult::Error();
+ return TPResult::Error;
// If annotation failed, assume it's a non-type.
// FIXME: If this happens due to an undeclared identifier, treat it as
// ambiguous.
if (Tok.is(tok::identifier))
- return TPResult::False();
+ return TPResult::False;
}
// We annotated this token as something. Recurse to handle whatever we got.
@@ -1206,21 +1171,21 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
// Annotate typenames and C++ scope specifiers. If we get one, just
// recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
- return TPResult::Error();
+ return TPResult::Error;
return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);
case tok::coloncolon: { // ::foo::bar
const Token &Next = NextToken();
if (Next.is(tok::kw_new) || // ::new
Next.is(tok::kw_delete)) // ::delete
- return TPResult::False();
+ return TPResult::False;
}
// Fall through.
case tok::kw_decltype:
// Annotate typenames and C++ scope specifiers. If we get one, just
// recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
- return TPResult::Error();
+ return TPResult::Error;
return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);
// decl-specifier:
@@ -1277,7 +1242,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::kw_restrict:
case tok::kw__Complex:
case tok::kw___attribute:
- return TPResult::True();
+ return TPResult::True;
// Microsoft
case tok::kw___declspec:
@@ -1292,20 +1257,20 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::kw___ptr32:
case tok::kw___forceinline:
case tok::kw___unaligned:
- return TPResult::True();
+ return TPResult::True;
// Borland
case tok::kw___pascal:
- return TPResult::True();
+ return TPResult::True;
// AltiVec
case tok::kw___vector:
- return TPResult::True();
+ return TPResult::True;
case tok::annot_template_id: {
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
if (TemplateId->Kind != TNK_Type_template)
- return TPResult::False();
+ return TPResult::False;
CXXScopeSpec SS;
AnnotateTemplateIdTokenAsType();
assert(Tok.is(tok::annot_typename));
@@ -1315,7 +1280,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed
// We've already annotated a scope; try to annotate a type.
if (TryAnnotateTypeOrScopeToken())
- return TPResult::Error();
+ return TPResult::Error;
if (!Tok.is(tok::annot_typename)) {
// If the next token is an identifier or a type qualifier, then this
// can't possibly be a valid expression either.
@@ -1329,37 +1294,37 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
ConsumeToken();
ConsumeToken();
bool isIdentifier = Tok.is(tok::identifier);
- TPResult TPR = TPResult::False();
+ TPResult TPR = TPResult::False;
if (!isIdentifier)
TPR = isCXXDeclarationSpecifier(BracedCastResult,
HasMissingTypename);
PA.Revert();
if (isIdentifier ||
- TPR == TPResult::True() || TPR == TPResult::Error())
- return TPResult::Error();
+ TPR == TPResult::True || TPR == TPResult::Error)
+ return TPResult::Error;
if (HasMissingTypename) {
// We can't tell whether this is a missing 'typename' or a valid
// expression.
*HasMissingTypename = true;
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
} else {
// Try to resolve the name. If it doesn't exist, assume it was
// intended to name a type and keep disambiguating.
switch (TryAnnotateName(false /* SS is not dependent */)) {
case ANK_Error:
- return TPResult::Error();
+ return TPResult::Error;
case ANK_TentativeDecl:
- return TPResult::False();
+ return TPResult::False;
case ANK_TemplateName:
// A bare type template-name which can't be a template template
// argument is an error, and was probably intended to be a type.
- return GreaterThanIsOperator ? TPResult::True() : TPResult::False();
+ return GreaterThanIsOperator ? TPResult::True : TPResult::False;
case ANK_Unresolved:
- return HasMissingTypename ? TPResult::Ambiguous()
- : TPResult::False();
+ return HasMissingTypename ? TPResult::Ambiguous
+ : TPResult::False;
case ANK_Success:
// Annotated it, check again.
assert(Tok.isNot(tok::annot_cxxscope) ||
@@ -1369,7 +1334,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
}
}
}
- return TPResult::False();
+ return TPResult::False;
}
// If that succeeded, fallthrough into the generic simple-type-id case.
@@ -1405,16 +1370,16 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
PA.Revert();
- if (TPR == TPResult::Error())
- return TPResult::Error();
+ if (TPR == TPResult::Error)
+ return TPResult::Error;
if (isFollowedByParen)
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
if (getLangOpts().CPlusPlus11 && isFollowedByBrace)
return BracedCastResult;
- return TPResult::True();
+ return TPResult::True;
}
case tok::kw_char:
@@ -1435,7 +1400,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::kw_void:
case tok::annot_decltype:
if (NextToken().is(tok::l_paren))
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
// This is a function-style cast in all cases we disambiguate other than
// one:
@@ -1447,14 +1412,14 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
return BracedCastResult;
if (isStartOfObjCClassMessageMissingOpenBracket())
- return TPResult::False();
+ return TPResult::False;
- return TPResult::True();
+ return TPResult::True;
// GNU typeof support.
case tok::kw_typeof: {
if (NextToken().isNot(tok::l_paren))
- return TPResult::True();
+ return TPResult::True;
TentativeParsingAction PA(*this);
@@ -1464,28 +1429,28 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
PA.Revert();
- if (TPR == TPResult::Error())
- return TPResult::Error();
+ if (TPR == TPResult::Error)
+ return TPResult::Error;
if (isFollowedByParen)
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
if (getLangOpts().CPlusPlus11 && isFollowedByBrace)
return BracedCastResult;
- return TPResult::True();
+ return TPResult::True;
}
// C++0x type traits support
case tok::kw___underlying_type:
- return TPResult::True();
+ return TPResult::True;
// C11 _Atomic
case tok::kw__Atomic:
- return TPResult::True();
+ return TPResult::True;
default:
- return TPResult::False();
+ return TPResult::False;
}
}
@@ -1551,9 +1516,9 @@ Parser::TPResult Parser::TryParseTypeofSpecifier() {
// Parse through the parens after 'typeof'.
ConsumeParen();
if (!SkipUntil(tok::r_paren, StopAtSemi))
- return TPResult::Error();
+ return TPResult::Error;
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
/// [ObjC] protocol-qualifiers:
@@ -1563,7 +1528,7 @@ Parser::TPResult Parser::TryParseProtocolQualifiers() {
ConsumeToken();
do {
if (Tok.isNot(tok::identifier))
- return TPResult::Error();
+ return TPResult::Error;
ConsumeToken();
if (Tok.is(tok::comma)) {
@@ -1573,11 +1538,11 @@ Parser::TPResult Parser::TryParseProtocolQualifiers() {
if (Tok.is(tok::greater)) {
ConsumeToken();
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
} while (false);
- return TPResult::Error();
+ return TPResult::Error;
}
/// isCXXFunctionDeclarator - Disambiguates between a function declarator or
@@ -1606,9 +1571,9 @@ bool Parser::isCXXFunctionDeclarator(bool *IsAmbiguous) {
ConsumeParen();
bool InvalidAsDeclaration = false;
TPResult TPR = TryParseParameterDeclarationClause(&InvalidAsDeclaration);
- if (TPR == TPResult::Ambiguous()) {
+ if (TPR == TPResult::Ambiguous) {
if (Tok.isNot(tok::r_paren))
- TPR = TPResult::False();
+ TPR = TPResult::False;
else {
const Token &Next = NextToken();
if (Next.is(tok::amp) || Next.is(tok::ampamp) ||
@@ -1620,20 +1585,20 @@ bool Parser::isCXXFunctionDeclarator(bool *IsAmbiguous) {
// The next token cannot appear after a constructor-style initializer,
// and can appear next in a function definition. This must be a function
// declarator.
- TPR = TPResult::True();
+ TPR = TPResult::True;
else if (InvalidAsDeclaration)
// Use the absence of 'typename' as a tie-breaker.
- TPR = TPResult::False();
+ TPR = TPResult::False;
}
}
PA.Revert();
- if (IsAmbiguous && TPR == TPResult::Ambiguous())
+ if (IsAmbiguous && TPR == TPResult::Ambiguous)
*IsAmbiguous = true;
// In case of an error, let the declaration parsing code handle it.
- return TPR != TPResult::False();
+ return TPR != TPResult::False;
}
/// parameter-declaration-clause:
@@ -1658,7 +1623,7 @@ Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration,
bool VersusTemplateArgument) {
if (Tok.is(tok::r_paren))
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
// parameter-declaration-list[opt] '...'[opt]
// parameter-declaration-list ',' '...'
@@ -1672,15 +1637,15 @@ Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration,
if (Tok.is(tok::ellipsis)) {
ConsumeToken();
if (Tok.is(tok::r_paren))
- return TPResult::True(); // '...)' is a sign of a function declarator.
+ return TPResult::True; // '...)' is a sign of a function declarator.
else
- return TPResult::False();
+ return TPResult::False;
}
// An attribute-specifier-seq here is a sign of a function declarator.
if (isCXX11AttributeSpecifier(/*Disambiguate*/false,
/*OuterMightBeMessageSend*/true))
- return TPResult::True();
+ return TPResult::True;
ParsedAttributes attrs(AttrFactory);
MaybeParseMicrosoftAttributes(attrs);
@@ -1688,43 +1653,43 @@ Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration,
// decl-specifier-seq
// A parameter-declaration's initializer must be preceded by an '=', so
// decl-specifier-seq '{' is not a parameter in C++11.
- TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(),
+ TPResult TPR = isCXXDeclarationSpecifier(TPResult::False,
InvalidAsDeclaration);
- if (VersusTemplateArgument && TPR == TPResult::True()) {
+ if (VersusTemplateArgument && TPR == TPResult::True) {
// Consume the decl-specifier-seq. We have to look past it, since a
// type-id might appear here in a template argument.
bool SeenType = false;
do {
SeenType |= isCXXDeclarationSpecifierAType();
- if (TryConsumeDeclarationSpecifier() == TPResult::Error())
- return TPResult::Error();
+ if (TryConsumeDeclarationSpecifier() == TPResult::Error)
+ return TPResult::Error;
// If we see a parameter name, this can't be a template argument.
if (SeenType && Tok.is(tok::identifier))
- return TPResult::True();
+ return TPResult::True;
- TPR = isCXXDeclarationSpecifier(TPResult::False(),
+ TPR = isCXXDeclarationSpecifier(TPResult::False,
InvalidAsDeclaration);
- if (TPR == TPResult::Error())
+ if (TPR == TPResult::Error)
return TPR;
- } while (TPR != TPResult::False());
- } else if (TPR == TPResult::Ambiguous()) {
+ } while (TPR != TPResult::False);
+ } else if (TPR == TPResult::Ambiguous) {
// Disambiguate what follows the decl-specifier.
- if (TryConsumeDeclarationSpecifier() == TPResult::Error())
- return TPResult::Error();
+ if (TryConsumeDeclarationSpecifier() == TPResult::Error)
+ return TPResult::Error;
} else
return TPR;
// declarator
// abstract-declarator[opt]
TPR = TryParseDeclarator(true/*mayBeAbstract*/);
- if (TPR != TPResult::Ambiguous())
+ if (TPR != TPResult::Ambiguous)
return TPR;
// [GNU] attributes[opt]
if (Tok.is(tok::kw___attribute))
- return TPResult::True();
+ return TPResult::True;
// If we're disambiguating a template argument in a default argument in
// a class definition versus a parameter declaration, an '=' here
@@ -1737,37 +1702,36 @@ 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.is(tok::equal) || Tok.is(tok::r_paren)) ? TPResult::True
+ : TPResult::False;
if (Tok.is(tok::equal)) {
// '=' assignment-expression
// Parse through assignment-expression.
// FIXME: assignment-expression may contain an unparenthesized comma.
if (!SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch))
- return TPResult::Error();
+ return TPResult::Error;
}
if (Tok.is(tok::ellipsis)) {
ConsumeToken();
if (Tok.is(tok::r_paren))
- return TPResult::True(); // '...)' is a sign of a function declarator.
+ return TPResult::True; // '...)' is a sign of a function declarator.
else
- return TPResult::False();
+ return TPResult::False;
}
- if (Tok.isNot(tok::comma))
+ if (!TryConsumeToken(tok::comma))
break;
- ConsumeToken(); // the comma.
}
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue
/// parsing as a function declarator.
/// If TryParseFunctionDeclarator fully parsed the function declarator, it will
-/// return TPResult::Ambiguous(), otherwise it will return either False() or
+/// return TPResult::Ambiguous, otherwise it will return either False() or
/// Error().
///
/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
@@ -1781,15 +1745,15 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() {
// The '(' is already parsed.
TPResult TPR = TryParseParameterDeclarationClause();
- if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren))
- TPR = TPResult::False();
+ if (TPR == TPResult::Ambiguous && Tok.isNot(tok::r_paren))
+ TPR = TPResult::False;
- if (TPR == TPResult::False() || TPR == TPResult::Error())
+ if (TPR == TPResult::False || TPR == TPResult::Error)
return TPR;
// Parse through the parens.
if (!SkipUntil(tok::r_paren, StopAtSemi))
- return TPResult::Error();
+ return TPResult::Error;
// cv-qualifier-seq
while (Tok.is(tok::kw_const) ||
@@ -1805,12 +1769,12 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() {
if (Tok.is(tok::kw_throw)) {
ConsumeToken();
if (Tok.isNot(tok::l_paren))
- return TPResult::Error();
+ return TPResult::Error;
// Parse through the parens after 'throw'.
ConsumeParen();
if (!SkipUntil(tok::r_paren, StopAtSemi))
- return TPResult::Error();
+ return TPResult::Error;
}
if (Tok.is(tok::kw_noexcept)) {
ConsumeToken();
@@ -1819,11 +1783,11 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() {
// Find the matching rparen.
ConsumeParen();
if (!SkipUntil(tok::r_paren, StopAtSemi))
- return TPResult::Error();
+ return TPResult::Error;
}
}
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
/// '[' constant-expression[opt] ']'
@@ -1831,7 +1795,7 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() {
Parser::TPResult Parser::TryParseBracketDeclarator() {
ConsumeBracket();
if (!SkipUntil(tok::r_square, StopAtSemi))
- return TPResult::Error();
+ return TPResult::Error;
- return TPResult::Ambiguous();
+ return TPResult::Ambiguous;
}
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 457dd36cbe9b..37ce157e0812 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -12,9 +12,9 @@
//===----------------------------------------------------------------------===//
#include "clang/Parse/Parser.h"
-#include "ParsePragma.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"
@@ -33,7 +33,7 @@ class ActionCommentHandler : public CommentHandler {
public:
explicit ActionCommentHandler(Sema &S) : S(S) { }
- virtual bool HandleComment(Preprocessor &PP, SourceRange Comment) {
+ bool HandleComment(Preprocessor &PP, SourceRange Comment) override {
S.ActOnComment(Comment);
return false;
}
@@ -56,58 +56,14 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies)
SkipFunctionBodies = pp.isCodeCompletionEnabled() || skipFunctionBodies;
Tok.startToken();
Tok.setKind(tok::eof);
- Actions.CurScope = 0;
+ Actions.CurScope = nullptr;
NumCachedScopes = 0;
ParenCount = BracketCount = BraceCount = 0;
- CurParsedObjCImpl = 0;
+ CurParsedObjCImpl = nullptr;
// Add #pragma handlers. These are removed and destroyed in the
// destructor.
- AlignHandler.reset(new PragmaAlignHandler());
- PP.AddPragmaHandler(AlignHandler.get());
-
- GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
- PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
-
- OptionsHandler.reset(new PragmaOptionsHandler());
- PP.AddPragmaHandler(OptionsHandler.get());
-
- PackHandler.reset(new PragmaPackHandler());
- PP.AddPragmaHandler(PackHandler.get());
-
- MSStructHandler.reset(new PragmaMSStructHandler());
- PP.AddPragmaHandler(MSStructHandler.get());
-
- UnusedHandler.reset(new PragmaUnusedHandler());
- PP.AddPragmaHandler(UnusedHandler.get());
-
- WeakHandler.reset(new PragmaWeakHandler());
- PP.AddPragmaHandler(WeakHandler.get());
-
- RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
- PP.AddPragmaHandler(RedefineExtnameHandler.get());
-
- FPContractHandler.reset(new PragmaFPContractHandler());
- PP.AddPragmaHandler("STDC", FPContractHandler.get());
-
- if (getLangOpts().OpenCL) {
- OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
- PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
-
- PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
- }
- if (getLangOpts().OpenMP)
- OpenMPHandler.reset(new PragmaOpenMPHandler());
- else
- OpenMPHandler.reset(new PragmaNoOpenMPHandler());
- PP.AddPragmaHandler(OpenMPHandler.get());
-
- if (getLangOpts().MicrosoftExt) {
- MSCommentHandler.reset(new PragmaCommentHandler(actions));
- PP.AddPragmaHandler(MSCommentHandler.get());
- MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(actions));
- PP.AddPragmaHandler(MSDetectMismatchHandler.get());
- }
+ initializePragmaHandlers();
CommentSemaHandler.reset(new ActionCommentHandler(actions));
PP.addCommentHandler(CommentSemaHandler.get());
@@ -152,14 +108,8 @@ static bool IsCommonTypo(tok::TokenKind ExpectedTok, const Token &Tok) {
}
}
-/// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the
-/// input. If so, it is consumed and false is returned.
-///
-/// If the input is malformed, this emits the specified diagnostic. Next, if
-/// SkipToTok is specified, it calls SkipUntil(SkipToTok). Finally, true is
-/// returned.
bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID,
- const char *Msg, tok::TokenKind SkipToTok) {
+ StringRef Msg) {
if (Tok.is(ExpectedTok) || Tok.is(tok::code_completion)) {
ConsumeAnyToken();
return false;
@@ -168,35 +118,48 @@ bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID,
// Detect common single-character typos and resume.
if (IsCommonTypo(ExpectedTok, Tok)) {
SourceLocation Loc = Tok.getLocation();
- Diag(Loc, DiagID)
- << Msg
- << FixItHint::CreateReplacement(SourceRange(Loc),
- getTokenSimpleSpelling(ExpectedTok));
- ConsumeAnyToken();
+ {
+ DiagnosticBuilder DB = Diag(Loc, DiagID);
+ DB << FixItHint::CreateReplacement(
+ SourceRange(Loc), tok::getPunctuatorSpelling(ExpectedTok));
+ if (DiagID == diag::err_expected)
+ DB << ExpectedTok;
+ else if (DiagID == diag::err_expected_after)
+ DB << Msg << ExpectedTok;
+ else
+ DB << Msg;
+ }
// Pretend there wasn't a problem.
+ ConsumeAnyToken();
return false;
}
- const char *Spelling = 0;
SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation);
- if (EndLoc.isValid() &&
- (Spelling = tok::getTokenSimpleSpelling(ExpectedTok))) {
- // Show what code to insert to fix this problem.
- Diag(EndLoc, DiagID)
- << Msg
- << FixItHint::CreateInsertion(EndLoc, Spelling);
- } else
- Diag(Tok, DiagID) << Msg;
+ const char *Spelling = nullptr;
+ if (EndLoc.isValid())
+ Spelling = tok::getPunctuatorSpelling(ExpectedTok);
+
+ DiagnosticBuilder DB =
+ Spelling
+ ? Diag(EndLoc, DiagID) << FixItHint::CreateInsertion(EndLoc, Spelling)
+ : Diag(Tok, DiagID);
+ if (DiagID == diag::err_expected)
+ DB << ExpectedTok;
+ else if (DiagID == diag::err_expected_after)
+ DB << Msg << ExpectedTok;
+ else
+ DB << Msg;
- if (SkipToTok != tok::unknown)
- SkipUntil(SkipToTok, StopAtSemi);
return true;
}
bool Parser::ExpectAndConsumeSemi(unsigned DiagID) {
- if (Tok.is(tok::semi) || Tok.is(tok::code_completion)) {
- ConsumeToken();
+ if (TryConsumeToken(tok::semi))
+ return false;
+
+ if (Tok.is(tok::code_completion)) {
+ handleUnexpectedCodeCompletionToken();
return false;
}
@@ -241,7 +204,8 @@ void Parser::ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST) {
if (Kind != AfterMemberFunctionDefinition || HadMultipleSemis)
Diag(StartLoc, diag::ext_extra_semi)
- << Kind << DeclSpec::getSpecifierName((DeclSpec::TST)TST)
+ << Kind << DeclSpec::getSpecifierName((DeclSpec::TST)TST,
+ Actions.getASTContext().getPrintingPolicy())
<< FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc));
else
// A single semicolon is valid after a member function definition.
@@ -288,7 +252,7 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) {
if (Toks.size() == 1 && Toks[0] == tok::eof &&
!HasFlagsSet(Flags, StopAtSemi) &&
!HasFlagsSet(Flags, StopAtCodeCompletion)) {
- while (Tok.getKind() != tok::eof)
+ while (Tok.isNot(tok::eof))
ConsumeAnyToken();
return true;
}
@@ -297,10 +261,20 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) {
case tok::eof:
// Ran out of tokens.
return false;
-
+
+ case tok::annot_pragma_openmp_end:
+ // Stop before an OpenMP pragma boundary.
+ case tok::annot_module_begin:
+ case tok::annot_module_end:
+ case tok::annot_module_include:
+ // Stop before we change submodules. They generally indicate a "good"
+ // place to pick up parsing again (except in the special case where
+ // we're trying to skip to EOF).
+ return false;
+
case tok::code_completion:
if (!HasFlagsSet(Flags, StopAtCodeCompletion))
- ConsumeToken();
+ handleUnexpectedCodeCompletionToken();
return false;
case tok::l_paren:
@@ -391,8 +365,7 @@ void Parser::ExitScope() {
// Inform the actions module that this scope is going away if there are any
// decls in it.
- if (!getCurScope()->decl_empty())
- Actions.ActOnPopScope(Tok.getLocation(), getCurScope());
+ Actions.ActOnPopScope(Tok.getLocation(), getCurScope());
Scope *OldScope = getCurScope();
Actions.CurScope = OldScope->getParent();
@@ -407,7 +380,7 @@ void Parser::ExitScope() {
/// this object does nothing.
Parser::ParseScopeFlags::ParseScopeFlags(Parser *Self, unsigned ScopeFlags,
bool ManageFlags)
- : CurScope(ManageFlags ? Self->getCurScope() : 0) {
+ : CurScope(ManageFlags ? Self->getCurScope() : nullptr) {
if (CurScope) {
OldFlags = CurScope->getFlags();
CurScope->setFlags(ScopeFlags);
@@ -429,47 +402,13 @@ Parser::ParseScopeFlags::~ParseScopeFlags() {
Parser::~Parser() {
// If we still have scopes active, delete the scope tree.
delete getCurScope();
- Actions.CurScope = 0;
-
+ Actions.CurScope = nullptr;
+
// Free the scope cache.
for (unsigned i = 0, e = NumCachedScopes; i != e; ++i)
delete ScopeCache[i];
- // Remove the pragma handlers we installed.
- PP.RemovePragmaHandler(AlignHandler.get());
- AlignHandler.reset();
- PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
- GCCVisibilityHandler.reset();
- PP.RemovePragmaHandler(OptionsHandler.get());
- OptionsHandler.reset();
- PP.RemovePragmaHandler(PackHandler.get());
- PackHandler.reset();
- PP.RemovePragmaHandler(MSStructHandler.get());
- MSStructHandler.reset();
- PP.RemovePragmaHandler(UnusedHandler.get());
- UnusedHandler.reset();
- PP.RemovePragmaHandler(WeakHandler.get());
- WeakHandler.reset();
- PP.RemovePragmaHandler(RedefineExtnameHandler.get());
- RedefineExtnameHandler.reset();
-
- if (getLangOpts().OpenCL) {
- PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
- OpenCLExtensionHandler.reset();
- PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
- }
- PP.RemovePragmaHandler(OpenMPHandler.get());
- OpenMPHandler.reset();
-
- if (getLangOpts().MicrosoftExt) {
- PP.RemovePragmaHandler(MSCommentHandler.get());
- MSCommentHandler.reset();
- PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
- MSDetectMismatchHandler.reset();
- }
-
- PP.RemovePragmaHandler("STDC", FPContractHandler.get());
- FPContractHandler.reset();
+ resetPragmaHandlers();
PP.removeCommentHandler(CommentSemaHandler.get());
@@ -482,7 +421,7 @@ Parser::~Parser() {
///
void Parser::Initialize() {
// Create the translation unit scope. Install it as the current scope.
- assert(getCurScope() == 0 && "A scope is already active?");
+ assert(getCurScope() == nullptr && "A scope is already active?");
EnterScope(Scope::DeclScope);
Actions.ActOnTranslationUnitScope(getCurScope());
@@ -497,10 +436,10 @@ void Parser::Initialize() {
ObjCTypeQuals[objc_byref] = &PP.getIdentifierTable().get("byref");
}
- Ident_instancetype = 0;
- Ident_final = 0;
- Ident_sealed = 0;
- Ident_override = 0;
+ Ident_instancetype = nullptr;
+ Ident_final = nullptr;
+ Ident_sealed = nullptr;
+ Ident_override = nullptr;
Ident_super = &PP.getIdentifierTable().get("super");
@@ -510,16 +449,18 @@ void Parser::Initialize() {
Ident_bool = &PP.getIdentifierTable().get("bool");
}
- Ident_introduced = 0;
- Ident_deprecated = 0;
- Ident_obsoleted = 0;
- Ident_unavailable = 0;
+ Ident_introduced = nullptr;
+ Ident_deprecated = nullptr;
+ Ident_obsoleted = nullptr;
+ Ident_unavailable = nullptr;
- Ident__except = 0;
-
- Ident__exception_code = Ident__exception_info = Ident__abnormal_termination = 0;
- Ident___exception_code = Ident___exception_info = Ident___abnormal_termination = 0;
- Ident_GetExceptionCode = Ident_GetExceptionInfo = Ident_AbnormalTermination = 0;
+ Ident__except = nullptr;
+
+ Ident__exception_code = Ident__exception_info = nullptr;
+ Ident__abnormal_termination = Ident___exception_code = nullptr;
+ Ident___exception_info = Ident___abnormal_termination = nullptr;
+ Ident_GetExceptionCode = Ident_GetExceptionInfo = nullptr;
+ Ident_AbnormalTermination = nullptr;
if(getLangOpts().Borland) {
Ident__exception_info = PP.getIdentifierInfo("_exception_info");
@@ -574,7 +515,7 @@ namespace {
bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds);
- // Skip over the EOF token, flagging end of previous input for incremental
+ // Skip over the EOF token, flagging end of previous input for incremental
// processing
if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof))
ConsumeToken();
@@ -592,6 +533,12 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
ConsumeToken();
return false;
+ case tok::annot_module_begin:
+ case tok::annot_module_end:
+ // FIXME: Update visibility based on the submodule we're in.
+ ConsumeToken();
+ return false;
+
case tok::eof:
// Late template parsing can begin.
if (getLangOpts().DelayedTemplateParsing)
@@ -647,7 +594,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
return DeclGroupPtrTy();
}
- Decl *SingleDecl = 0;
+ Decl *SingleDecl = nullptr;
switch (Tok.getKind()) {
case tok::annot_pragma_vis:
HandlePragmaVisibility();
@@ -679,6 +626,15 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
case tok::annot_pragma_openmp:
ParseOpenMPDeclarativeDirective();
return DeclGroupPtrTy();
+ case tok::annot_pragma_ms_pointers_to_members:
+ HandlePragmaMSPointersToMembers();
+ return DeclGroupPtrTy();
+ case tok::annot_pragma_ms_vtordisp:
+ HandlePragmaMSVtorDisp();
+ return DeclGroupPtrTy();
+ case tok::annot_pragma_ms_pragma:
+ HandlePragmaMSPragma();
+ return DeclGroupPtrTy();
case tok::semi:
// Either a C++11 empty-declaration or attribute-declaration.
SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(),
@@ -706,7 +662,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
SourceLocation EndLoc;
ExprResult Result(ParseSimpleAsm(&EndLoc));
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
+ ExpectAndConsume(tok::semi, diag::err_expected_after,
"top-level asm block");
if (Result.isInvalid())
@@ -793,7 +749,6 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
ParseExplicitInstantiation(Declarator::FileContext,
ExternLoc, TemplateLoc, DeclEnd));
}
- // FIXME: Detect C++ linkage specifications here?
goto dont_know;
case tok::kw___if_exists:
@@ -907,9 +862,10 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
DS.abort();
- const char *PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
- if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID))
+ if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID,
+ Actions.getASTContext().getPrintingPolicy()))
Diag(AtLoc, DiagID) << PrevSpec;
if (Tok.isObjCAtKeyword(tok::objc_protocol))
@@ -922,7 +878,7 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
// If the declspec consisted only of 'extern' and we have a string
// literal following it, this must be a C++ linkage specifier like
// 'extern "C"'.
- if (Tok.is(tok::string_literal) && getLangOpts().CPlusPlus &&
+ if (getLangOpts().CPlusPlus && isTokenStringLiteral() &&
DS.getStorageClassSpec() == DeclSpec::SCS_extern &&
DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) {
Decl *TheDecl = ParseLinkage(DS, Declarator::FileContext);
@@ -949,26 +905,6 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributesWithRange &attrs,
}
}
-
-static inline bool isFunctionDeclaratorRequiringReturnTypeDeduction(
- const Declarator &D) {
- if (!D.isFunctionDeclarator() || !D.getDeclSpec().containsPlaceholderType())
- return false;
- for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) {
- unsigned chunkIndex = E - I - 1;
- const DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
- if (DeclType.Kind == DeclaratorChunk::Function) {
- const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
- if (!FTI.hasTrailingReturnType())
- return true;
- QualType TrailingRetType = FTI.getTrailingReturnType().get();
- return TrailingRetType->getCanonicalTypeInternal()
- ->getContainedAutoType();
- }
- }
- return false;
-}
-
/// ParseFunctionDefinition - We parsed and verified that the specified
/// Declarator is well formed. If this is a K&R-style function, read the
/// parameters declaration-list, then start the compound-statement.
@@ -996,9 +932,11 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
if (getLangOpts().ImplicitInt && D.getDeclSpec().isEmpty()) {
const char *PrevSpec;
unsigned DiagID;
+ const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
D.getMutableDeclSpec().SetTypeSpecType(DeclSpec::TST_int,
D.getIdentifierLoc(),
- PrevSpec, DiagID);
+ PrevSpec, DiagID,
+ Policy);
D.SetRangeBegin(D.getDeclSpec().getSourceRange().getBegin());
}
@@ -1021,7 +959,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
// If we didn't find the '{', bail out.
if (Tok.isNot(tok::l_brace))
- return 0;
+ return nullptr;
}
// Check to make sure that any normal attributes are allowed to be on
@@ -1029,10 +967,10 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
if (Tok.isNot(tok::equal)) {
AttributeList *DtorAttrs = D.getAttributes();
while (DtorAttrs) {
- if (!IsThreadSafetyAttribute(DtorAttrs->getName()->getName()) &&
+ if (DtorAttrs->isKnownToGCC() &&
!DtorAttrs->isCXX11Attribute()) {
Diag(DtorAttrs->getLoc(), diag::warn_attribute_on_function_definition)
- << DtorAttrs->getName()->getName();
+ << DtorAttrs->getName();
}
DtorAttrs = DtorAttrs->getNext();
}
@@ -1042,8 +980,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
// tokens and store them for late parsing at the end of the translation unit.
if (getLangOpts().DelayedTemplateParsing && Tok.isNot(tok::equal) &&
TemplateInfo.Kind == ParsedTemplateInfo::Template &&
- !D.getDeclSpec().isConstexprSpecified() &&
- !isFunctionDeclaratorRequiringReturnTypeDeduction(D)) {
+ Actions.canDelayFunctionBody(D)) {
MultiTemplateParamsArg TemplateParameterLists(*TemplateInfo.TemplateParams);
ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
@@ -1059,12 +996,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
LexTemplateFunctionForLateParsing(Toks);
if (DP) {
- FunctionDecl *FnD = 0;
- if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(DP))
- FnD = FunTmpl->getTemplatedDecl();
- else
- FnD = cast<FunctionDecl>(DP);
-
+ FunctionDecl *FnD = DP->getAsFunction();
Actions.CheckForFunctionRedefinition(FnD);
Actions.MarkAsLateParsedTemplate(FnD, DP, Toks);
}
@@ -1077,7 +1009,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
Actions.CurContext->isTranslationUnit()) {
ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
Scope *ParentScope = getCurScope()->getParent();
-
+
D.setFunctionDefinitionKind(FDK_Definition);
Decl *FuncDecl = Actions.HandleDeclarator(ParentScope, D,
MultiTemplateParamsArg());
@@ -1089,8 +1021,9 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
CurParsedObjCImpl->HasCFunction = true;
return FuncDecl;
}
+ // FIXME: Should we really fall through here?
}
-
+
// Enter a scope for the function body.
ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
@@ -1108,28 +1041,22 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
// safe because we're always the sole owner.
D.getMutableDeclSpec().abort();
- if (Tok.is(tok::equal)) {
+ if (TryConsumeToken(tok::equal)) {
assert(getLangOpts().CPlusPlus && "Only C++ function definitions have '='");
- ConsumeToken();
+ Actions.ActOnFinishFunctionBody(Res, nullptr, false);
- Actions.ActOnFinishFunctionBody(Res, 0, false);
-
bool Delete = false;
SourceLocation KWLoc;
- if (Tok.is(tok::kw_delete)) {
- Diag(Tok, getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_deleted_function :
- diag::ext_deleted_function);
-
- KWLoc = ConsumeToken();
+ if (TryConsumeToken(tok::kw_delete, KWLoc)) {
+ Diag(KWLoc, getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_deleted_function
+ : diag::ext_deleted_function);
Actions.SetDeclDeleted(Res, KWLoc);
Delete = true;
- } else if (Tok.is(tok::kw_default)) {
- Diag(Tok, getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_defaulted_function :
- diag::ext_defaulted_function);
-
- KWLoc = ConsumeToken();
+ } else if (TryConsumeToken(tok::kw_default, KWLoc)) {
+ Diag(KWLoc, getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_defaulted_function
+ : diag::ext_defaulted_function);
Actions.SetDeclDefaulted(Res, KWLoc);
} else {
llvm_unreachable("function definition after = not 'delete' or 'default'");
@@ -1139,9 +1066,9 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
Diag(KWLoc, diag::err_default_delete_in_multiple_declaration)
<< Delete;
SkipUntil(tok::semi);
- } else {
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
- Delete ? "delete" : "default", tok::semi);
+ } else if (ExpectAndConsume(tok::semi, diag::err_expected_after,
+ Delete ? "delete" : "default")) {
+ SkipUntil(tok::semi);
}
return Res;
@@ -1158,7 +1085,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
// Recover from error.
if (!Tok.is(tok::l_brace)) {
BodyScope.Exit();
- Actions.ActOnFinishFunctionBody(Res, 0);
+ Actions.ActOnFinishFunctionBody(Res, nullptr);
return Res;
}
} else
@@ -1195,9 +1122,8 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
// NOTE: GCC just makes this an ext-warn. It's not clear what it does with
// the declarations though. It's trivial to ignore them, really hard to do
// anything else with them.
- if (Tok.is(tok::semi)) {
+ if (TryConsumeToken(tok::semi)) {
Diag(DSStart, diag::err_declaration_does_not_declare_param);
- ConsumeToken();
continue;
}
@@ -1237,20 +1163,20 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
for (unsigned i = 0; ; ++i) {
// C99 6.9.1p6: those declarators shall declare only identifiers from
// the identifier list.
- if (i == FTI.NumArgs) {
+ if (i == FTI.NumParams) {
Diag(ParmDeclarator.getIdentifierLoc(), diag::err_no_matching_param)
<< ParmDeclarator.getIdentifier();
break;
}
- if (FTI.ArgInfo[i].Ident == ParmDeclarator.getIdentifier()) {
+ if (FTI.Params[i].Ident == ParmDeclarator.getIdentifier()) {
// Reject redefinitions of parameters.
- if (FTI.ArgInfo[i].Param) {
+ if (FTI.Params[i].Param) {
Diag(ParmDeclarator.getIdentifierLoc(),
diag::err_param_redefinition)
<< ParmDeclarator.getIdentifier();
} else {
- FTI.ArgInfo[i].Param = Param;
+ FTI.Params[i].Param = Param;
}
break;
}
@@ -1271,12 +1197,14 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
ParseDeclarator(ParmDeclarator);
}
- if (ExpectAndConsumeSemi(diag::err_expected_semi_declaration)) {
- // Skip to end of block or statement
- SkipUntil(tok::semi);
- if (Tok.is(tok::semi))
- ConsumeToken();
- }
+ // Consume ';' and continue parsing.
+ if (!ExpectAndConsumeSemi(diag::err_expected_semi_declaration))
+ continue;
+
+ // Otherwise recover by skipping to next semi or mandatory function body.
+ if (SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch))
+ break;
+ TryConsumeToken(tok::semi);
}
// The actions module must verify that all arguments were declared.
@@ -1340,16 +1268,15 @@ Parser::ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) {
ExprResult Result(ParseAsmStringLiteral());
- if (Result.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
- if (EndLoc)
- *EndLoc = Tok.getLocation();
- ConsumeAnyToken();
- } else {
+ if (!Result.isInvalid()) {
// Close the paren and get the location of the end bracket
T.consumeClose();
if (EndLoc)
*EndLoc = T.getCloseLocation();
+ } else if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) {
+ if (EndLoc)
+ *EndLoc = Tok.getLocation();
+ ConsumeParen();
}
return Result;
@@ -1430,11 +1357,11 @@ Parser::TryAnnotateName(bool IsAddressOfOperand,
// Look up and classify the identifier. We don't perform any typo-correction
// after a scope specifier, because in general we can't recover from typos
- // there (eg, after correcting 'A::tempalte B<X>::C', we would need to jump
- // back into scope specifier parsing).
+ // there (eg, after correcting 'A::tempalte B<X>::C' [sic], we would need to
+ // jump back into scope specifier parsing).
Sema::NameClassification Classification
= Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, Next,
- IsAddressOfOperand, SS.isEmpty() ? CCC : 0);
+ IsAddressOfOperand, SS.isEmpty() ? CCC : nullptr);
switch (Classification.getKind()) {
case Sema::NC_Error:
@@ -1504,16 +1431,34 @@ Parser::TryAnnotateName(bool IsAddressOfOperand,
}
bool Parser::TryKeywordIdentFallback(bool DisableKeyword) {
- assert(Tok.isNot(tok::identifier));
+ assert(!Tok.is(tok::identifier) && !Tok.isAnnotation());
Diag(Tok, diag::ext_keyword_as_ident)
<< PP.getSpelling(Tok)
<< DisableKeyword;
- if (DisableKeyword)
- Tok.getIdentifierInfo()->RevertTokenIDToIdentifier();
+ if (DisableKeyword) {
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ ContextualKeywords[II] = Tok.getKind();
+ II->RevertTokenIDToIdentifier();
+ }
Tok.setKind(tok::identifier);
return true;
}
+bool Parser::TryIdentKeywordUpgrade() {
+ assert(Tok.is(tok::identifier));
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ assert(II->hasRevertedTokenIDToIdentifier());
+ // If we find that this is in fact the name of a type trait,
+ // update the token kind in place and parse again to treat it as
+ // the appropriate kind of type trait.
+ llvm::SmallDenseMap<const IdentifierInfo *, tok::TokenKind>::iterator Known =
+ ContextualKeywords.find(II);
+ if (Known == ContextualKeywords.end())
+ return false;
+ Tok.setKind(Known->second);
+ return true;
+}
+
/// TryAnnotateTypeOrScopeToken - If the current token position is on a
/// typename (possibly qualified in C++) or a C++ scope specifier not followed
/// by a typename, TryAnnotateTypeOrScopeToken will replace one or more tokens
@@ -1549,7 +1494,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) {
// We will consume the typedef token here and put it back after we have
// parsed the first identifier, transforming it into something more like:
// typename T_::D typedef D;
- if (getLangOpts().MicrosoftMode && NextToken().is(tok::kw_typedef)) {
+ if (getLangOpts().MSVCCompat && NextToken().is(tok::kw_typedef)) {
Token TypedefToken;
PP.Lex(TypedefToken);
bool Result = TryAnnotateTypeOrScopeToken(EnteringContext, NeedType);
@@ -1570,7 +1515,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) {
CXXScopeSpec SS;
if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/ParsedType(),
/*EnteringContext=*/false,
- 0, /*IsTypename*/true))
+ nullptr, /*IsTypename*/ true))
return true;
if (!SS.isSet()) {
if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id) ||
@@ -1601,7 +1546,8 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) {
Tok.getLocation());
} else if (Tok.is(tok::annot_template_id)) {
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
- if (TemplateId->Kind == TNK_Function_template) {
+ if (TemplateId->Kind != TNK_Type_template &&
+ TemplateId->Kind != TNK_Dependent_template_name) {
Diag(Tok, diag::err_typename_refers_to_non_type_template)
<< Tok.getAnnotationRange();
return true;
@@ -1652,7 +1598,7 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext,
CXXScopeSpec &SS,
bool IsNewScope) {
if (Tok.is(tok::identifier)) {
- IdentifierInfo *CorrectedII = 0;
+ IdentifierInfo *CorrectedII = nullptr;
// Determine whether the identifier is a type name.
if (ParsedType Ty = Actions.getTypeName(*Tok.getIdentifierInfo(),
Tok.getLocation(), getCurScope(),
@@ -1660,8 +1606,9 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext,
NextToken().is(tok::period),
ParsedType(),
/*IsCtorOrDtorName=*/false,
- /*NonTrivialTypeSourceInfo*/true,
- NeedType ? &CorrectedII : NULL)) {
+ /*NonTrivialTypeSourceInfo*/ true,
+ NeedType ? &CorrectedII
+ : nullptr)) {
// A FixIt was applied as a result of typo correction
if (CorrectedII)
Tok.setIdentifierInfo(CorrectedII);
@@ -1725,8 +1672,7 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext,
// annotation token to a type annotation token now.
AnnotateTemplateIdTokenAsType();
return false;
- } else if (TemplateId->Kind == TNK_Var_template)
- return false;
+ }
}
if (SS.isEmpty())
@@ -1780,8 +1726,8 @@ bool Parser::isTokenEqualOrEqualTypo() {
case tok::pipeequal: // |=
case tok::equalequal: // ==
Diag(Tok, diag::err_invalid_token_after_declarator_suggest_equal)
- << getTokenSimpleSpelling(Kind)
- << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()), "=");
+ << Kind
+ << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()), "=");
case tok::equal:
return true;
}
@@ -1910,7 +1856,7 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() {
BalancedDelimiterTracker Braces(*this, tok::l_brace);
if (Braces.consumeOpen()) {
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
return;
}
@@ -1928,14 +1874,15 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() {
}
// Parse the declarations.
- while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ // FIXME: Support module import within __if_exists?
+ while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
MaybeParseMicrosoftAttributes(attrs);
DeclGroupPtrTy Result = ParseExternalDeclaration(attrs);
if (Result && !getCurScope()->getParent())
Actions.getASTConsumer().HandleTopLevelDecl(Result.get());
- }
+ }
Braces.consumeClose();
}
@@ -1951,8 +1898,7 @@ Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) {
if (!Tok.is(tok::identifier)) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteModuleImport(ImportLoc, Path);
- ConsumeCodeCompletionToken();
- SkipUntil(tok::semi);
+ cutOffParsing();
return DeclGroupPtrTy();
}
@@ -1991,17 +1937,20 @@ bool BalancedDelimiterTracker::diagnoseOverflow() {
P.Diag(P.Tok, diag::err_bracket_depth_exceeded)
<< P.getLangOpts().BracketDepth;
P.Diag(P.Tok, diag::note_bracket_depth);
- P.SkipUntil(tok::eof);
- return true;
+ P.cutOffParsing();
+ return true;
}
bool BalancedDelimiterTracker::expectAndConsume(unsigned DiagID,
- const char *Msg,
- tok::TokenKind SkipToToc ) {
+ const char *Msg,
+ tok::TokenKind SkipToTok) {
LOpen = P.Tok.getLocation();
- if (P.ExpectAndConsume(Kind, DiagID, Msg, SkipToToc))
+ if (P.ExpectAndConsume(Kind, DiagID, Msg)) {
+ if (SkipToTok != tok::unknown)
+ P.SkipUntil(SkipToTok, Parser::StopAtSemi);
return true;
-
+ }
+
if (getDepth() < MaxDepth)
return false;
@@ -2010,17 +1959,9 @@ bool BalancedDelimiterTracker::expectAndConsume(unsigned DiagID,
bool BalancedDelimiterTracker::diagnoseMissingClose() {
assert(!P.Tok.is(Close) && "Should have consumed closing delimiter");
-
- const char *LHSName = "unknown";
- diag::kind DID;
- switch (Close) {
- default: llvm_unreachable("Unexpected balanced token");
- case tok::r_paren : LHSName = "("; DID = diag::err_expected_rparen; break;
- case tok::r_brace : LHSName = "{"; DID = diag::err_expected_rbrace; break;
- case tok::r_square: LHSName = "["; DID = diag::err_expected_rsquare; break;
- }
- P.Diag(P.Tok, DID);
- P.Diag(LOpen, diag::note_matching) << LHSName;
+
+ P.Diag(P.Tok, diag::err_expected) << Close;
+ P.Diag(LOpen, diag::note_matching) << Kind;
// If we're not already at some kind of closing bracket, skip to our closing
// token.
diff --git a/lib/Parse/RAIIObjectsForParser.h b/lib/Parse/RAIIObjectsForParser.h
index f68a2e09fe91..4f5f3ab81036 100644
--- a/lib/Parse/RAIIObjectsForParser.h
+++ b/lib/Parse/RAIIObjectsForParser.h
@@ -50,7 +50,7 @@ namespace clang {
public:
/// Begin suppressing access-like checks
SuppressAccessChecks(Parser &P, bool activate = true)
- : S(P.getActions()), DiagnosticPool(NULL) {
+ : S(P.getActions()), DiagnosticPool(nullptr) {
if (activate) {
State = S.PushParsingDeclaration(DiagnosticPool);
Active = true;
@@ -61,7 +61,7 @@ namespace clang {
void done() {
assert(Active && "trying to end an inactive suppression");
- S.PopParsingDeclaration(State, NULL);
+ S.PopParsingDeclaration(State, nullptr);
Active = false;
}
@@ -93,7 +93,7 @@ namespace clang {
public:
enum NoParent_t { NoParent };
ParsingDeclRAIIObject(Parser &P, NoParent_t _)
- : Actions(P.getActions()), DiagnosticPool(NULL) {
+ : Actions(P.getActions()), DiagnosticPool(nullptr) {
push();
}
@@ -109,7 +109,7 @@ namespace clang {
/// RAII object (which is assumed to be the current top pool).
ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *other)
: Actions(P.getActions()),
- DiagnosticPool(other ? other->DiagnosticPool.getParent() : NULL) {
+ DiagnosticPool(other ? other->DiagnosticPool.getParent() : nullptr) {
if (other) {
DiagnosticPool.steal(other->DiagnosticPool);
other->abort();
@@ -137,7 +137,7 @@ namespace clang {
/// Signals that the context was completed without an appropriate
/// declaration being parsed.
void abort() {
- pop(0);
+ pop(nullptr);
}
void complete(Decl *D) {
@@ -148,7 +148,7 @@ namespace clang {
/// Unregister this object from Sema, but remember all the
/// diagnostics that were emitted into it.
void abortAndRemember() {
- pop(0);
+ pop(nullptr);
}
private:
@@ -415,8 +415,8 @@ namespace clang {
return diagnoseOverflow();
}
-
- bool expectAndConsume(unsigned DiagID,
+
+ bool expectAndConsume(unsigned DiagID = diag::err_expected,
const char *Msg = "",
tok::TokenKind SkipToTok = tok::unknown);
bool consumeClose() {