aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/Parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse/Parser.cpp')
-rw-r--r--lib/Parse/Parser.cpp219
1 files changed, 177 insertions, 42 deletions
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index f968f995d53f..d8a4ea63153a 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -20,7 +20,6 @@
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
-#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -78,7 +77,6 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies)
Tok.setKind(tok::eof);
Actions.CurScope = nullptr;
NumCachedScopes = 0;
- ParenCount = BracketCount = BraceCount = 0;
CurParsedObjCImpl = nullptr;
// Add #pragma handlers. These are removed and destroyed in the
@@ -474,6 +472,7 @@ void Parser::Initialize() {
Ident_final = nullptr;
Ident_sealed = nullptr;
Ident_override = nullptr;
+ Ident_GNU_final = nullptr;
Ident_super = &PP.getIdentifierTable().get("super");
@@ -537,6 +536,36 @@ void Parser::LateTemplateParserCleanupCallback(void *P) {
DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(((Parser *)P)->TemplateIds);
}
+bool Parser::ParseFirstTopLevelDecl(DeclGroupPtrTy &Result) {
+ // C++ Modules TS: module-declaration must be the first declaration in the
+ // file. (There can be no preceding preprocessor directives, but we expect
+ // the lexer to check that.)
+ if (Tok.is(tok::kw_module)) {
+ Result = ParseModuleDecl();
+ return false;
+ } else if (getLangOpts().getCompilingModule() ==
+ LangOptions::CMK_ModuleInterface) {
+ // FIXME: We avoid providing this diagnostic when generating an object file
+ // from an existing PCM file. This is not a good way to detect this
+ // condition; we should provide a mechanism to indicate whether we've
+ // already parsed a declaration in this translation unit and avoid calling
+ // ParseFirstTopLevelDecl in that case.
+ if (Actions.TUKind == TU_Module)
+ Diag(Tok, diag::err_expected_module_interface_decl);
+ }
+
+ // C11 6.9p1 says translation units must have at least one top-level
+ // declaration. C++ doesn't have this restriction. We also don't want to
+ // complain if we have a precompiled header, although technically if the PCH
+ // is empty we should still emit the (pedantic) diagnostic.
+ bool NoTopLevelDecls = ParseTopLevelDecl(Result);
+ if (NoTopLevelDecls && !Actions.getASTContext().getExternalSource() &&
+ !getLangOpts().CPlusPlus)
+ Diag(diag::ext_empty_translation_unit);
+
+ return NoTopLevelDecls;
+}
+
/// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
/// action tells us to. This returns true if the EOF was encountered.
bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
@@ -553,6 +582,10 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
HandlePragmaUnused();
return false;
+ case tok::kw_import:
+ Result = ParseModuleImport(SourceLocation());
+ return false;
+
case tok::annot_module_include:
Actions.ActOnModuleInclude(Tok.getLocation(),
reinterpret_cast<Module *>(
@@ -590,7 +623,6 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
- MaybeParseMicrosoftAttributes(attrs);
Result = ParseExternalDeclaration(attrs);
return false;
@@ -737,11 +769,17 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
: Sema::PCC_Namespace);
cutOffParsing();
return nullptr;
+ case tok::kw_export:
+ if (getLangOpts().ModulesTS) {
+ SingleDecl = ParseExportDeclaration();
+ break;
+ }
+ // This must be 'export template'. Parse it so we can diagnose our lack
+ // of support.
case tok::kw_using:
case tok::kw_namespace:
case tok::kw_typedef:
case tok::kw_template:
- case tok::kw_export: // As in 'export template'
case tok::kw_static_assert:
case tok::kw__Static_assert:
// A function definition cannot start with any of these keywords.
@@ -802,6 +840,11 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
ParseMicrosoftIfExistsExternalDeclaration();
return nullptr;
+ case tok::kw_module:
+ Diag(Tok, diag::err_unexpected_module_decl);
+ SkipUntil(tok::semi);
+ return nullptr;
+
default:
dont_know:
// We can't tell whether this is a function-definition or declaration yet.
@@ -853,11 +896,10 @@ bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) {
Tok.is(tok::kw_try); // X() try { ... }
}
-/// ParseDeclarationOrFunctionDefinition - Parse either a function-definition or
-/// a declaration. We can't tell which we have until we read up to the
-/// compound-statement in function-definition. TemplateParams, if
-/// non-NULL, provides the template parameters when we're parsing a
-/// C++ template-declaration.
+/// Parse either a function-definition or a declaration. We can't tell which
+/// we have until we read up to the compound-statement in function-definition.
+/// TemplateParams, if non-NULL, provides the template parameters when we're
+/// parsing a C++ template-declaration.
///
/// function-definition: [C99 6.9.1]
/// decl-specs declarator declaration-list[opt] compound-statement
@@ -873,6 +915,7 @@ Parser::DeclGroupPtrTy
Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
ParsingDeclSpec &DS,
AccessSpecifier AS) {
+ MaybeParseMicrosoftAttributes(DS.getAttributes());
// Parse the common declaration-specifiers piece.
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC_top_level);
@@ -891,6 +934,8 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none,
DS, AnonRecord);
DS.complete(TheDecl);
+ if (getLangOpts().OpenCL)
+ Actions.setCurrentOpenCLExtensionForDecl(TheDecl);
if (AnonRecord) {
Decl* decls[] = {AnonRecord, TheDecl};
return Actions.BuildDeclaratorGroup(decls, /*TypeMayContainAuto=*/false);
@@ -952,7 +997,7 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributesWithRange &attrs,
// parsing c constructs and re-enter objc container scope
// afterwards.
ObjCDeclContextSwitch ObjCDC(*this);
-
+
return ParseDeclOrFunctionDefInternal(attrs, PDS, AS);
}
}
@@ -1495,6 +1540,8 @@ Parser::TryAnnotateName(bool IsAddressOfOperand,
NewEndLoc);
if (NewType.isUsable())
Ty = NewType.get();
+ else if (Tok.is(tok::eof)) // Nothing to do here, bail out...
+ return ANK_Error;
}
Tok.setKind(tok::annot_typename);
@@ -1726,6 +1773,8 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext,
NewEndLoc);
if (NewType.isUsable())
Ty = NewType.get();
+ else if (Tok.is(tok::eof)) // Nothing to do here, bail out...
+ return false;
}
// This is a typename. Replace the current token in-place with an
@@ -1988,7 +2037,6 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() {
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());
@@ -1996,51 +2044,122 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() {
Braces.consumeClose();
}
+/// Parse a C++ Modules TS module declaration, which appears at the beginning
+/// of a module interface, module partition, or module implementation file.
+///
+/// module-declaration: [Modules TS + P0273R0]
+/// 'module' module-kind[opt] module-name attribute-specifier-seq[opt] ';'
+/// module-kind:
+/// 'implementation'
+/// 'partition'
+///
+/// Note that the module-kind values are context-sensitive keywords.
+Parser::DeclGroupPtrTy Parser::ParseModuleDecl() {
+ assert(Tok.is(tok::kw_module) && getLangOpts().ModulesTS &&
+ "should not be parsing a module declaration");
+ SourceLocation ModuleLoc = ConsumeToken();
+
+ // Check for a module-kind.
+ Sema::ModuleDeclKind MDK = Sema::ModuleDeclKind::Module;
+ if (Tok.is(tok::identifier) && NextToken().is(tok::identifier)) {
+ if (Tok.getIdentifierInfo()->isStr("implementation"))
+ MDK = Sema::ModuleDeclKind::Implementation;
+ else if (Tok.getIdentifierInfo()->isStr("partition"))
+ MDK = Sema::ModuleDeclKind::Partition;
+ else {
+ Diag(Tok, diag::err_unexpected_module_kind) << Tok.getIdentifierInfo();
+ SkipUntil(tok::semi);
+ return nullptr;
+ }
+ ConsumeToken();
+ }
+
+ SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
+ if (ParseModuleName(ModuleLoc, Path, /*IsImport*/false))
+ return nullptr;
+
+ ParsedAttributesWithRange Attrs(AttrFactory);
+ MaybeParseCXX11Attributes(Attrs);
+ // We don't support any module attributes yet.
+ ProhibitCXX11Attributes(Attrs, diag::err_attribute_not_module_attr);
+
+ ExpectAndConsumeSemi(diag::err_module_expected_semi);
+
+ return Actions.ActOnModuleDecl(ModuleLoc, MDK, Path);
+}
+
+/// Parse a module import declaration. This is essentially the same for
+/// Objective-C and the C++ Modules TS, except for the leading '@' (in ObjC)
+/// and the trailing optional attributes (in C++).
+///
+/// [ObjC] @import declaration:
+/// '@' 'import' module-name ';'
+/// [ModTS] module-import-declaration:
+/// 'import' module-name attribute-specifier-seq[opt] ';'
Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) {
- assert(Tok.isObjCAtKeyword(tok::objc_import) &&
+ assert((AtLoc.isInvalid() ? Tok.is(tok::kw_import)
+ : Tok.isObjCAtKeyword(tok::objc_import)) &&
"Improper start to module import");
SourceLocation ImportLoc = ConsumeToken();
+ SourceLocation StartLoc = AtLoc.isInvalid() ? ImportLoc : AtLoc;
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
-
+ if (ParseModuleName(ImportLoc, Path, /*IsImport*/true))
+ return nullptr;
+
+ ParsedAttributesWithRange Attrs(AttrFactory);
+ MaybeParseCXX11Attributes(Attrs);
+ // We don't support any module import attributes yet.
+ ProhibitCXX11Attributes(Attrs, diag::err_attribute_not_import_attr);
+
+ if (PP.hadModuleLoaderFatalFailure()) {
+ // With a fatal failure in the module loader, we abort parsing.
+ cutOffParsing();
+ return nullptr;
+ }
+
+ DeclResult Import = Actions.ActOnModuleImport(StartLoc, ImportLoc, Path);
+ ExpectAndConsumeSemi(diag::err_module_expected_semi);
+ if (Import.isInvalid())
+ return nullptr;
+
+ return Actions.ConvertDeclToDeclGroup(Import.get());
+}
+
+/// Parse a C++ Modules TS / Objective-C module name (both forms use the same
+/// grammar).
+///
+/// module-name:
+/// module-name-qualifier[opt] identifier
+/// module-name-qualifier:
+/// module-name-qualifier[opt] identifier '.'
+bool Parser::ParseModuleName(
+ SourceLocation UseLoc,
+ SmallVectorImpl<std::pair<IdentifierInfo *, SourceLocation>> &Path,
+ bool IsImport) {
// Parse the module path.
- do {
+ while (true) {
if (!Tok.is(tok::identifier)) {
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteModuleImport(ImportLoc, Path);
+ Actions.CodeCompleteModuleImport(UseLoc, Path);
cutOffParsing();
- return nullptr;
+ return true;
}
- Diag(Tok, diag::err_module_expected_ident);
+ Diag(Tok, diag::err_module_expected_ident) << IsImport;
SkipUntil(tok::semi);
- return nullptr;
+ return true;
}
// Record this part of the module path.
Path.push_back(std::make_pair(Tok.getIdentifierInfo(), Tok.getLocation()));
ConsumeToken();
-
- if (Tok.is(tok::period)) {
- ConsumeToken();
- continue;
- }
-
- break;
- } while (true);
- if (PP.hadModuleLoaderFatalFailure()) {
- // With a fatal failure in the module loader, we abort parsing.
- cutOffParsing();
- return nullptr;
- }
-
- DeclResult Import = Actions.ActOnModuleImport(AtLoc, ImportLoc, Path);
- ExpectAndConsumeSemi(diag::err_module_expected_semi);
- if (Import.isInvalid())
- return nullptr;
+ if (Tok.isNot(tok::period))
+ return false;
- return Actions.ConvertDeclToDeclGroup(Import.get());
+ ConsumeToken();
+ }
}
/// \brief Try recover parser when module annotation appears where it must not
@@ -2051,19 +2170,35 @@ bool Parser::parseMisplacedModuleImport() {
while (true) {
switch (Tok.getKind()) {
case tok::annot_module_end:
+ // If we recovered from a misplaced module begin, we expect to hit a
+ // misplaced module end too. Stay in the current context when this
+ // happens.
+ if (MisplacedModuleBeginCount) {
+ --MisplacedModuleBeginCount;
+ Actions.ActOnModuleEnd(Tok.getLocation(),
+ reinterpret_cast<Module *>(
+ Tok.getAnnotationValue()));
+ ConsumeToken();
+ continue;
+ }
// Inform caller that recovery failed, the error must be handled at upper
- // level.
+ // level. This will generate the desired "missing '}' at end of module"
+ // diagnostics on the way out.
return true;
case tok::annot_module_begin:
- Actions.diagnoseMisplacedModuleImport(reinterpret_cast<Module *>(
- Tok.getAnnotationValue()), Tok.getLocation());
- return true;
+ // Recover by entering the module (Sema will diagnose).
+ Actions.ActOnModuleBegin(Tok.getLocation(),
+ reinterpret_cast<Module *>(
+ Tok.getAnnotationValue()));
+ ConsumeToken();
+ ++MisplacedModuleBeginCount;
+ continue;
case tok::annot_module_include:
// Module import found where it should not be, for instance, inside a
// namespace. Recover by importing the module.
Actions.ActOnModuleInclude(Tok.getLocation(),
reinterpret_cast<Module *>(
- Tok.getAnnotationValue()));
+ Tok.getAnnotationValue()));
ConsumeToken();
// If there is another module import, process it.
continue;