r279163 - C++ Modules TS: Add parsing support for module import declaration.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 18 14:59:42 PDT 2016
Author: rsmith
Date: Thu Aug 18 16:59:42 2016
New Revision: 279163
URL: http://llvm.org/viewvc/llvm-project?rev=279163&view=rev
Log:
C++ Modules TS: Add parsing support for module import declaration.
Added:
cfe/trunk/test/Parser/cxx-modules-import.cpp
Modified:
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/Lex/Preprocessor.cpp
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/Parser.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=279163&r1=279162&r2=279163&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Thu Aug 18 16:59:42 2016
@@ -1023,6 +1023,8 @@ def warn_pragma_unroll_cuda_value_in_par
let CategoryName = "Modules Issue" in {
def err_module_expected_ident : Error<
"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<
"expected ';' after module name">;
def err_missing_before_module_end : Error<"expected %0 at end of module">;
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=279163&r1=279162&r2=279163&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Thu Aug 18 16:59:42 2016
@@ -2116,7 +2116,8 @@ private:
// Forbid C++11 attributes that appear on certain syntactic
// locations which standard permits but we don't supported yet,
// 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.
/// \returns SourceLocation() if there are no attributes.
Modified: cfe/trunk/lib/Lex/Preprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Preprocessor.cpp?rev=279163&r1=279162&r2=279163&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/Preprocessor.cpp (original)
+++ cfe/trunk/lib/Lex/Preprocessor.cpp Thu Aug 18 16:59:42 2016
@@ -712,9 +712,12 @@ bool Preprocessor::HandleIdentifier(Toke
// Note that we do not treat 'import' as a contextual
// keyword when we're in a caching lexer, because caching lexers only get
// used in contexts where import declarations are disallowed.
- if (LastTokenWasAt && II.isModulesImport() && !InMacroArgs &&
- !DisableMacroExpansion &&
- (getLangOpts().Modules || getLangOpts().DebuggerSupport) &&
+ //
+ // Likewise if this is the C++ Modules TS import keyword.
+ if (((LastTokenWasAt && II.isModulesImport()) ||
+ Identifier.is(tok::kw_import)) &&
+ !InMacroArgs && !DisableMacroExpansion &&
+ (getLangOpts().Modules || getLangOpts().DebuggerSupport) &&
CurLexerKind != CLK_CachingLexer) {
ModuleImportLoc = Identifier.getLocation();
ModuleImportPath.clear();
@@ -782,7 +785,8 @@ void Preprocessor::LexAfterModuleImport(
}
// 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) {
ModuleImportExpectsIdentifier = true;
CurLexerKind = CLK_LexAfterModuleImport;
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=279163&r1=279162&r2=279163&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Aug 18 16:59:42 2016
@@ -1407,15 +1407,19 @@ void Parser::DiagnoseProhibitedAttribute
<< attrs.Range;
}
-void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs) {
- AttributeList *AttrList = attrs.getList();
- while (AttrList) {
- if (AttrList->isCXX11Attribute()) {
- Diag(AttrList->getLoc(), diag::err_attribute_not_type_attr)
- << AttrList->getName();
- AttrList->setInvalid();
+void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs,
+ unsigned DiagID) {
+ for (AttributeList *Attr = Attrs.getList(); Attr; Attr = Attr->getNext()) {
+ if (!Attr->isCXX11Attribute())
+ continue;
+ if (Attr->getKind() == AttributeList::UnknownAttribute)
+ 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(
// Reject C++11 attributes that appertain to decl specifiers as
// we don't support any C++11 attributes that appertain to decl
// specifiers. This also conforms to what g++ 4.8 is doing.
- ProhibitCXX11Attributes(attrs);
+ ProhibitCXX11Attributes(attrs, diag::err_attribute_not_type_attr);
DS.takeAttributesFrom(attrs);
}
Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=279163&r1=279162&r2=279163&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Thu Aug 18 16:59:42 2016
@@ -553,6 +553,10 @@ bool Parser::ParseTopLevelDecl(DeclGroup
HandlePragmaUnused();
return false;
+ case tok::kw_import:
+ Result = ParseModuleImport(SourceLocation());
+ return false;
+
case tok::annot_module_include:
Actions.ActOnModuleInclude(Tok.getLocation(),
reinterpret_cast<Module *>(
@@ -1996,15 +2000,29 @@ void Parser::ParseMicrosoftIfExistsExter
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) {
- 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;
// Parse the module path.
- do {
+ while (true) {
if (!Tok.is(tok::identifier)) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteModuleImport(ImportLoc, Path);
@@ -2020,14 +2038,17 @@ Parser::DeclGroupPtrTy Parser::ParseModu
// 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 (Tok.isNot(tok::period))
+ break;
+
+ ConsumeToken();
+ }
+
+ 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.
@@ -2035,7 +2056,7 @@ Parser::DeclGroupPtrTy Parser::ParseModu
return nullptr;
}
- DeclResult Import = Actions.ActOnModuleImport(AtLoc, ImportLoc, Path);
+ DeclResult Import = Actions.ActOnModuleImport(StartLoc, ImportLoc, Path);
ExpectAndConsumeSemi(diag::err_module_expected_semi);
if (Import.isInvalid())
return nullptr;
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=279163&r1=279162&r2=279163&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Aug 18 16:59:42 2016
@@ -15178,7 +15178,7 @@ void Sema::diagnoseMisplacedModuleImport
return checkModuleImportContext(*this, M, ImportLoc, CurContext);
}
-DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
+DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
SourceLocation ImportLoc,
ModuleIdPath Path) {
Module *Mod =
@@ -15213,8 +15213,7 @@ DeclResult Sema::ActOnModuleImport(Sourc
}
TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
- ImportDecl *Import = ImportDecl::Create(Context, TU,
- AtLoc.isValid()? AtLoc : ImportLoc,
+ ImportDecl *Import = ImportDecl::Create(Context, TU, StartLoc,
Mod, IdentifierLocs);
if (!ModuleScopes.empty())
Context.addModuleInitializer(ModuleScopes.back().Module, Import);
Added: cfe/trunk/test/Parser/cxx-modules-import.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-modules-import.cpp?rev=279163&view=auto
==============================================================================
--- cfe/trunk/test/Parser/cxx-modules-import.cpp (added)
+++ cfe/trunk/test/Parser/cxx-modules-import.cpp Thu Aug 18 16:59:42 2016
@@ -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}}
More information about the cfe-commits
mailing list