Skip to content

Commit ec9187d

Browse files
committed
C++ Modules TS: Add parsing support for module import declaration.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@279163 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 3a33970 commit ec9187d

File tree

7 files changed

+81
-28
lines changed

7 files changed

+81
-28
lines changed

include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,6 +1023,8 @@ def warn_pragma_unroll_cuda_value_in_parens : Warning<
10231023
let CategoryName = "Modules Issue" in {
10241024
def err_module_expected_ident : Error<
10251025
"expected a module name after module import">;
1026+
def err_attribute_not_import_attr : Error<
1027+
"%0 attribute cannot be applied to a module import">;
10261028
def err_module_expected_semi : Error<
10271029
"expected ';' after module name">;
10281030
def err_missing_before_module_end : Error<"expected %0 at end of module">;

include/clang/Parse/Parser.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2116,7 +2116,8 @@ class Parser : public CodeCompletionHandler {
21162116
// Forbid C++11 attributes that appear on certain syntactic
21172117
// locations which standard permits but we don't supported yet,
21182118
// for example, attributes appertain to decl specifiers.
2119-
void ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs);
2119+
void ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs,
2120+
unsigned DiagID);
21202121

21212122
/// \brief Skip C++11 attributes and return the end location of the last one.
21222123
/// \returns SourceLocation() if there are no attributes.

lib/Lex/Preprocessor.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -712,9 +712,12 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) {
712712
// Note that we do not treat 'import' as a contextual
713713
// keyword when we're in a caching lexer, because caching lexers only get
714714
// used in contexts where import declarations are disallowed.
715-
if (LastTokenWasAt && II.isModulesImport() && !InMacroArgs &&
716-
!DisableMacroExpansion &&
717-
(getLangOpts().Modules || getLangOpts().DebuggerSupport) &&
715+
//
716+
// Likewise if this is the C++ Modules TS import keyword.
717+
if (((LastTokenWasAt && II.isModulesImport()) ||
718+
Identifier.is(tok::kw_import)) &&
719+
!InMacroArgs && !DisableMacroExpansion &&
720+
(getLangOpts().Modules || getLangOpts().DebuggerSupport) &&
718721
CurLexerKind != CLK_CachingLexer) {
719722
ModuleImportLoc = Identifier.getLocation();
720723
ModuleImportPath.clear();
@@ -782,7 +785,8 @@ void Preprocessor::LexAfterModuleImport(Token &Result) {
782785
}
783786

784787
// If we're expecting a '.' or a ';', and we got a '.', then wait until we
785-
// see the next identifier.
788+
// see the next identifier. (We can also see a '[[' that begins an
789+
// attribute-specifier-seq here under the C++ Modules TS.)
786790
if (!ModuleImportExpectsIdentifier && Result.getKind() == tok::period) {
787791
ModuleImportExpectsIdentifier = true;
788792
CurLexerKind = CLK_LexAfterModuleImport;

lib/Parse/ParseDecl.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,15 +1407,19 @@ void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) {
14071407
<< attrs.Range;
14081408
}
14091409

1410-
void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs) {
1411-
AttributeList *AttrList = attrs.getList();
1412-
while (AttrList) {
1413-
if (AttrList->isCXX11Attribute()) {
1414-
Diag(AttrList->getLoc(), diag::err_attribute_not_type_attr)
1415-
<< AttrList->getName();
1416-
AttrList->setInvalid();
1410+
void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs,
1411+
unsigned DiagID) {
1412+
for (AttributeList *Attr = Attrs.getList(); Attr; Attr = Attr->getNext()) {
1413+
if (!Attr->isCXX11Attribute())
1414+
continue;
1415+
if (Attr->getKind() == AttributeList::UnknownAttribute)
1416+
Diag(Attr->getLoc(), diag::warn_unknown_attribute_ignored)
1417+
<< Attr->getName();
1418+
else {
1419+
Diag(Attr->getLoc(), DiagID)
1420+
<< Attr->getName();
1421+
Attr->setInvalid();
14171422
}
1418-
AttrList = AttrList->getNext();
14191423
}
14201424
}
14211425

@@ -2717,7 +2721,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
27172721
// Reject C++11 attributes that appertain to decl specifiers as
27182722
// we don't support any C++11 attributes that appertain to decl
27192723
// specifiers. This also conforms to what g++ 4.8 is doing.
2720-
ProhibitCXX11Attributes(attrs);
2724+
ProhibitCXX11Attributes(attrs, diag::err_attribute_not_type_attr);
27212725

27222726
DS.takeAttributesFrom(attrs);
27232727
}

lib/Parse/Parser.cpp

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,10 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
553553
HandlePragmaUnused();
554554
return false;
555555

556+
case tok::kw_import:
557+
Result = ParseModuleImport(SourceLocation());
558+
return false;
559+
556560
case tok::annot_module_include:
557561
Actions.ActOnModuleInclude(Tok.getLocation(),
558562
reinterpret_cast<Module *>(
@@ -1996,15 +2000,29 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() {
19962000
Braces.consumeClose();
19972001
}
19982002

2003+
/// Parse a module import declaration. This is essentially the same for
2004+
/// Objective-C and the C++ Modules TS, except for the leading '@' (in ObjC)
2005+
/// and the trailing optional attributes (in C++).
2006+
///
2007+
/// [ObjC] @import declaration:
2008+
/// '@' 'import' (identifier '.')* ';'
2009+
/// [ModTS] module-import-declaration:
2010+
/// 'module' module-name attribute-specifier-seq[opt] ';'
2011+
/// module-name:
2012+
/// module-name-qualifier[opt] identifier
2013+
/// module-name-qualifier:
2014+
/// module-name-qualifier[opt] identifier '.'
19992015
Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) {
2000-
assert(Tok.isObjCAtKeyword(tok::objc_import) &&
2016+
assert((AtLoc.isInvalid() ? Tok.is(tok::kw_import)
2017+
: Tok.isObjCAtKeyword(tok::objc_import)) &&
20012018
"Improper start to module import");
20022019
SourceLocation ImportLoc = ConsumeToken();
2020+
SourceLocation StartLoc = AtLoc.isInvalid() ? ImportLoc : AtLoc;
20032021

20042022
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
20052023

20062024
// Parse the module path.
2007-
do {
2025+
while (true) {
20082026
if (!Tok.is(tok::identifier)) {
20092027
if (Tok.is(tok::code_completion)) {
20102028
Actions.CodeCompleteModuleImport(ImportLoc, Path);
@@ -2020,22 +2038,25 @@ Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) {
20202038
// Record this part of the module path.
20212039
Path.push_back(std::make_pair(Tok.getIdentifierInfo(), Tok.getLocation()));
20222040
ConsumeToken();
2023-
2024-
if (Tok.is(tok::period)) {
2025-
ConsumeToken();
2026-
continue;
2027-
}
2028-
2029-
break;
2030-
} while (true);
2041+
2042+
if (Tok.isNot(tok::period))
2043+
break;
2044+
2045+
ConsumeToken();
2046+
}
2047+
2048+
ParsedAttributesWithRange Attrs(AttrFactory);
2049+
MaybeParseCXX11Attributes(Attrs);
2050+
// We don't support any module import attributes yet.
2051+
ProhibitCXX11Attributes(Attrs, diag::err_attribute_not_import_attr);
20312052

20322053
if (PP.hadModuleLoaderFatalFailure()) {
20332054
// With a fatal failure in the module loader, we abort parsing.
20342055
cutOffParsing();
20352056
return nullptr;
20362057
}
20372058

2038-
DeclResult Import = Actions.ActOnModuleImport(AtLoc, ImportLoc, Path);
2059+
DeclResult Import = Actions.ActOnModuleImport(StartLoc, ImportLoc, Path);
20392060
ExpectAndConsumeSemi(diag::err_module_expected_semi);
20402061
if (Import.isInvalid())
20412062
return nullptr;

lib/Sema/SemaDecl.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15178,7 +15178,7 @@ void Sema::diagnoseMisplacedModuleImport(Module *M, SourceLocation ImportLoc) {
1517815178
return checkModuleImportContext(*this, M, ImportLoc, CurContext);
1517915179
}
1518015180

15181-
DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
15181+
DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
1518215182
SourceLocation ImportLoc,
1518315183
ModuleIdPath Path) {
1518415184
Module *Mod =
@@ -15213,8 +15213,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
1521315213
}
1521415214

1521515215
TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
15216-
ImportDecl *Import = ImportDecl::Create(Context, TU,
15217-
AtLoc.isValid()? AtLoc : ImportLoc,
15216+
ImportDecl *Import = ImportDecl::Create(Context, TU, StartLoc,
1521815217
Mod, IdentifierLocs);
1521915218
if (!ModuleScopes.empty())
1522015219
Context.addModuleInitializer(ModuleScopes.back().Module, Import);

test/Parser/cxx-modules-import.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: echo 'int a, b;' > %t/x.h
4+
// RUN: echo 'module x { header "x.h" module y {} }' > %t/map
5+
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%S/Inputs -fmodules-cache-path=%t -fmodule-map-file=%t/map -verify %s
6+
7+
int use_1 = a; // expected-error {{undeclared}}
8+
9+
import x;
10+
11+
int use_2 = b; // ok
12+
13+
import x [[]];
14+
import x [[foo]]; // expected-warning {{unknown attribute 'foo' ignored}}
15+
import x [[noreturn]]; // expected-error {{'noreturn' attribute cannot be applied to a module import}}
16+
import x [[blarg::noreturn]]; // expected-warning {{unknown attribute 'noreturn' ignored}}
17+
18+
import x.y;
19+
import x.; // expected-error {{expected a module name after module import}}
20+
import .x; // expected-error {{expected a module name after module import}}
21+
22+
import blarg; // expected-error {{module 'blarg' not found}}

0 commit comments

Comments
 (0)