forked from OSchip/llvm-project
C++ Modules TS: Add parsing support for module import declaration.
llvm-svn: 279163
This commit is contained in:
parent
4071b1bac3
commit
49cc1ccb00
|
@ -1023,6 +1023,8 @@ def warn_pragma_unroll_cuda_value_in_parens : Warning<
|
||||||
let CategoryName = "Modules Issue" in {
|
let CategoryName = "Modules Issue" in {
|
||||||
def err_module_expected_ident : Error<
|
def err_module_expected_ident : Error<
|
||||||
"expected a module name after module import">;
|
"expected a module name after module import">;
|
||||||
|
def err_attribute_not_import_attr : Error<
|
||||||
|
"%0 attribute cannot be applied to a module import">;
|
||||||
def err_module_expected_semi : Error<
|
def err_module_expected_semi : Error<
|
||||||
"expected ';' after module name">;
|
"expected ';' after module name">;
|
||||||
def err_missing_before_module_end : Error<"expected %0 at end of module">;
|
def err_missing_before_module_end : Error<"expected %0 at end of module">;
|
||||||
|
|
|
@ -2116,7 +2116,8 @@ private:
|
||||||
// Forbid C++11 attributes that appear on certain syntactic
|
// Forbid C++11 attributes that appear on certain syntactic
|
||||||
// locations which standard permits but we don't supported yet,
|
// locations which standard permits but we don't supported yet,
|
||||||
// for example, attributes appertain to decl specifiers.
|
// for example, attributes appertain to decl specifiers.
|
||||||
void ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs);
|
void ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs,
|
||||||
|
unsigned DiagID);
|
||||||
|
|
||||||
/// \brief Skip C++11 attributes and return the end location of the last one.
|
/// \brief Skip C++11 attributes and return the end location of the last one.
|
||||||
/// \returns SourceLocation() if there are no attributes.
|
/// \returns SourceLocation() if there are no attributes.
|
||||||
|
|
|
@ -712,9 +712,12 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) {
|
||||||
// Note that we do not treat 'import' as a contextual
|
// Note that we do not treat 'import' as a contextual
|
||||||
// keyword when we're in a caching lexer, because caching lexers only get
|
// keyword when we're in a caching lexer, because caching lexers only get
|
||||||
// used in contexts where import declarations are disallowed.
|
// used in contexts where import declarations are disallowed.
|
||||||
if (LastTokenWasAt && II.isModulesImport() && !InMacroArgs &&
|
//
|
||||||
!DisableMacroExpansion &&
|
// Likewise if this is the C++ Modules TS import keyword.
|
||||||
(getLangOpts().Modules || getLangOpts().DebuggerSupport) &&
|
if (((LastTokenWasAt && II.isModulesImport()) ||
|
||||||
|
Identifier.is(tok::kw_import)) &&
|
||||||
|
!InMacroArgs && !DisableMacroExpansion &&
|
||||||
|
(getLangOpts().Modules || getLangOpts().DebuggerSupport) &&
|
||||||
CurLexerKind != CLK_CachingLexer) {
|
CurLexerKind != CLK_CachingLexer) {
|
||||||
ModuleImportLoc = Identifier.getLocation();
|
ModuleImportLoc = Identifier.getLocation();
|
||||||
ModuleImportPath.clear();
|
ModuleImportPath.clear();
|
||||||
|
@ -782,7 +785,8 @@ void Preprocessor::LexAfterModuleImport(Token &Result) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're expecting a '.' or a ';', and we got a '.', then wait until we
|
// If we're expecting a '.' or a ';', and we got a '.', then wait until we
|
||||||
// see the next identifier.
|
// see the next identifier. (We can also see a '[[' that begins an
|
||||||
|
// attribute-specifier-seq here under the C++ Modules TS.)
|
||||||
if (!ModuleImportExpectsIdentifier && Result.getKind() == tok::period) {
|
if (!ModuleImportExpectsIdentifier && Result.getKind() == tok::period) {
|
||||||
ModuleImportExpectsIdentifier = true;
|
ModuleImportExpectsIdentifier = true;
|
||||||
CurLexerKind = CLK_LexAfterModuleImport;
|
CurLexerKind = CLK_LexAfterModuleImport;
|
||||||
|
|
|
@ -1407,15 +1407,19 @@ void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) {
|
||||||
<< attrs.Range;
|
<< attrs.Range;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs) {
|
void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs,
|
||||||
AttributeList *AttrList = attrs.getList();
|
unsigned DiagID) {
|
||||||
while (AttrList) {
|
for (AttributeList *Attr = Attrs.getList(); Attr; Attr = Attr->getNext()) {
|
||||||
if (AttrList->isCXX11Attribute()) {
|
if (!Attr->isCXX11Attribute())
|
||||||
Diag(AttrList->getLoc(), diag::err_attribute_not_type_attr)
|
continue;
|
||||||
<< AttrList->getName();
|
if (Attr->getKind() == AttributeList::UnknownAttribute)
|
||||||
AttrList->setInvalid();
|
Diag(Attr->getLoc(), diag::warn_unknown_attribute_ignored)
|
||||||
|
<< Attr->getName();
|
||||||
|
else {
|
||||||
|
Diag(Attr->getLoc(), DiagID)
|
||||||
|
<< Attr->getName();
|
||||||
|
Attr->setInvalid();
|
||||||
}
|
}
|
||||||
AttrList = AttrList->getNext();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2717,7 +2721,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||||
// Reject C++11 attributes that appertain to decl specifiers as
|
// Reject C++11 attributes that appertain to decl specifiers as
|
||||||
// we don't support any C++11 attributes that appertain to decl
|
// we don't support any C++11 attributes that appertain to decl
|
||||||
// specifiers. This also conforms to what g++ 4.8 is doing.
|
// specifiers. This also conforms to what g++ 4.8 is doing.
|
||||||
ProhibitCXX11Attributes(attrs);
|
ProhibitCXX11Attributes(attrs, diag::err_attribute_not_type_attr);
|
||||||
|
|
||||||
DS.takeAttributesFrom(attrs);
|
DS.takeAttributesFrom(attrs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -553,6 +553,10 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
|
||||||
HandlePragmaUnused();
|
HandlePragmaUnused();
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
case tok::kw_import:
|
||||||
|
Result = ParseModuleImport(SourceLocation());
|
||||||
|
return false;
|
||||||
|
|
||||||
case tok::annot_module_include:
|
case tok::annot_module_include:
|
||||||
Actions.ActOnModuleInclude(Tok.getLocation(),
|
Actions.ActOnModuleInclude(Tok.getLocation(),
|
||||||
reinterpret_cast<Module *>(
|
reinterpret_cast<Module *>(
|
||||||
|
@ -1996,15 +2000,29 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() {
|
||||||
Braces.consumeClose();
|
Braces.consumeClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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' (identifier '.')* ';'
|
||||||
|
/// [ModTS] module-import-declaration:
|
||||||
|
/// 'module' module-name attribute-specifier-seq[opt] ';'
|
||||||
|
/// module-name:
|
||||||
|
/// module-name-qualifier[opt] identifier
|
||||||
|
/// module-name-qualifier:
|
||||||
|
/// module-name-qualifier[opt] identifier '.'
|
||||||
Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) {
|
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");
|
"Improper start to module import");
|
||||||
SourceLocation ImportLoc = ConsumeToken();
|
SourceLocation ImportLoc = ConsumeToken();
|
||||||
|
SourceLocation StartLoc = AtLoc.isInvalid() ? ImportLoc : AtLoc;
|
||||||
|
|
||||||
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
|
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
|
||||||
|
|
||||||
// Parse the module path.
|
// Parse the module path.
|
||||||
do {
|
while (true) {
|
||||||
if (!Tok.is(tok::identifier)) {
|
if (!Tok.is(tok::identifier)) {
|
||||||
if (Tok.is(tok::code_completion)) {
|
if (Tok.is(tok::code_completion)) {
|
||||||
Actions.CodeCompleteModuleImport(ImportLoc, Path);
|
Actions.CodeCompleteModuleImport(ImportLoc, Path);
|
||||||
|
@ -2020,14 +2038,17 @@ Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) {
|
||||||
// Record this part of the module path.
|
// Record this part of the module path.
|
||||||
Path.push_back(std::make_pair(Tok.getIdentifierInfo(), Tok.getLocation()));
|
Path.push_back(std::make_pair(Tok.getIdentifierInfo(), Tok.getLocation()));
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
|
|
||||||
if (Tok.is(tok::period)) {
|
if (Tok.isNot(tok::period))
|
||||||
ConsumeToken();
|
break;
|
||||||
continue;
|
|
||||||
}
|
ConsumeToken();
|
||||||
|
}
|
||||||
break;
|
|
||||||
} while (true);
|
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()) {
|
if (PP.hadModuleLoaderFatalFailure()) {
|
||||||
// With a fatal failure in the module loader, we abort parsing.
|
// With a fatal failure in the module loader, we abort parsing.
|
||||||
|
@ -2035,7 +2056,7 @@ Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclResult Import = Actions.ActOnModuleImport(AtLoc, ImportLoc, Path);
|
DeclResult Import = Actions.ActOnModuleImport(StartLoc, ImportLoc, Path);
|
||||||
ExpectAndConsumeSemi(diag::err_module_expected_semi);
|
ExpectAndConsumeSemi(diag::err_module_expected_semi);
|
||||||
if (Import.isInvalid())
|
if (Import.isInvalid())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -15178,7 +15178,7 @@ void Sema::diagnoseMisplacedModuleImport(Module *M, SourceLocation ImportLoc) {
|
||||||
return checkModuleImportContext(*this, M, ImportLoc, CurContext);
|
return checkModuleImportContext(*this, M, ImportLoc, CurContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
|
DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
|
||||||
SourceLocation ImportLoc,
|
SourceLocation ImportLoc,
|
||||||
ModuleIdPath Path) {
|
ModuleIdPath Path) {
|
||||||
Module *Mod =
|
Module *Mod =
|
||||||
|
@ -15213,8 +15213,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
|
||||||
}
|
}
|
||||||
|
|
||||||
TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
|
TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
|
||||||
ImportDecl *Import = ImportDecl::Create(Context, TU,
|
ImportDecl *Import = ImportDecl::Create(Context, TU, StartLoc,
|
||||||
AtLoc.isValid()? AtLoc : ImportLoc,
|
|
||||||
Mod, IdentifierLocs);
|
Mod, IdentifierLocs);
|
||||||
if (!ModuleScopes.empty())
|
if (!ModuleScopes.empty())
|
||||||
Context.addModuleInitializer(ModuleScopes.back().Module, Import);
|
Context.addModuleInitializer(ModuleScopes.back().Module, Import);
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
// RUN: rm -rf %t
|
||||||
|
// RUN: mkdir -p %t
|
||||||
|
// RUN: echo 'int a, b;' > %t/x.h
|
||||||
|
// RUN: echo 'module x { header "x.h" module y {} }' > %t/map
|
||||||
|
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%S/Inputs -fmodules-cache-path=%t -fmodule-map-file=%t/map -verify %s
|
||||||
|
|
||||||
|
int use_1 = a; // expected-error {{undeclared}}
|
||||||
|
|
||||||
|
import x;
|
||||||
|
|
||||||
|
int use_2 = b; // ok
|
||||||
|
|
||||||
|
import x [[]];
|
||||||
|
import x [[foo]]; // expected-warning {{unknown attribute 'foo' ignored}}
|
||||||
|
import x [[noreturn]]; // expected-error {{'noreturn' attribute cannot be applied to a module import}}
|
||||||
|
import x [[blarg::noreturn]]; // expected-warning {{unknown attribute 'noreturn' ignored}}
|
||||||
|
|
||||||
|
import x.y;
|
||||||
|
import x.; // expected-error {{expected a module name after module import}}
|
||||||
|
import .x; // expected-error {{expected a module name after module import}}
|
||||||
|
|
||||||
|
import blarg; // expected-error {{module 'blarg' not found}}
|
Loading…
Reference in New Issue