Skip to content

Commit 04ddbf6

Browse files
committed
[C++20][Modules] Implement P1857R3 Modules Dependency Discovery
Signed-off-by: yronglin <yronglin777@gmail.com>
1 parent 2cce3d1 commit 04ddbf6

File tree

42 files changed

+1376
-712
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1376
-712
lines changed

clang/examples/AnnotateFunctions/AnnotateFunctions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class PragmaAnnotateHandler : public PragmaHandler {
6565
Token Tok;
6666
PP.LexUnexpandedToken(Tok);
6767
if (Tok.isNot(tok::eod))
68-
PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
68+
PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "#pragma";
6969

7070
if (HandledDecl) {
7171
DiagnosticsEngine &D = PP.getDiagnostics();

clang/include/clang/Basic/DiagnosticLexKinds.td

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,9 @@ def err_pp_embed_device_file : Error<
466466

467467
def ext_pp_extra_tokens_at_eol : ExtWarn<
468468
"extra tokens at end of #%0 directive">, InGroup<ExtraTokens>;
469+
def ext_pp_extra_tokens_at_module_directive_eol
470+
: ExtWarn<"extra tokens at end of '%0' directive">,
471+
InGroup<ExtraTokens>;
469472

470473
def ext_pp_comma_expr : Extension<"comma operator in operand of #if">;
471474
def ext_pp_bad_vaargs_use : Extension<
@@ -495,8 +498,8 @@ def warn_cxx98_compat_variadic_macro : Warning<
495498
InGroup<CXX98CompatPedantic>, DefaultIgnore;
496499
def ext_named_variadic_macro : Extension<
497500
"named variadic macros are a GNU extension">, InGroup<VariadicMacros>;
498-
def err_embedded_directive : Error<
499-
"embedding a #%0 directive within macro arguments is not supported">;
501+
def err_embedded_directive : Error<"embedding a %select{#|C++ }0%1 directive "
502+
"within macro arguments is not supported">;
500503
def ext_embedded_directive : Extension<
501504
"embedding a directive within macro arguments has undefined behavior">,
502505
InGroup<DiagGroup<"embedded-directive">>;
@@ -983,6 +986,19 @@ def warn_module_conflict : Warning<
983986
InGroup<ModuleConflict>;
984987

985988
// C++20 modules
989+
def err_pp_expected_module_name_or_header_name
990+
: Error<"expected module name or header name">;
991+
def err_pp_expected_semi_after_module_or_import
992+
: Error<"'%select{module|import}0' directive must end with a ';' on the "
993+
"same line">;
994+
def err_module_decl_in_header
995+
: Error<"module declaration must not come from an #include directive">;
996+
def err_pp_cond_span_module_decl
997+
: Error<"preprocessor conditionals shall not span a module declaration">;
998+
def err_pp_module_expected_ident
999+
: Error<"expected a module name after '%select{module|import}0'">;
1000+
def err_pp_unsupported_module_partition
1001+
: Error<"module partitions are only supported for C++20 onwards">;
9861002
def err_header_import_semi_in_macro : Error<
9871003
"semicolon terminating header import declaration cannot be produced "
9881004
"by a macro">;

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1760,38 +1760,36 @@ def ext_bit_int : Extension<
17601760
} // end of Parse Issue category.
17611761

17621762
let CategoryName = "Modules Issue" in {
1763-
def err_unexpected_module_decl : Error<
1764-
"module declaration can only appear at the top level">;
1765-
def err_module_expected_ident : Error<
1766-
"expected a module name after '%select{module|import}0'">;
1767-
def err_attribute_not_module_attr : Error<
1768-
"%0 attribute cannot be applied to a module">;
1769-
def err_keyword_not_module_attr : Error<
1770-
"%0 cannot be applied to a module">;
1771-
def err_attribute_not_import_attr : Error<
1772-
"%0 attribute cannot be applied to a module import">;
1773-
def err_keyword_not_import_attr : Error<
1774-
"%0 cannot be applied to a module import">;
1775-
def err_module_expected_semi : Error<
1776-
"expected ';' after module name">;
1777-
def err_global_module_introducer_not_at_start : Error<
1778-
"'module;' introducing a global module fragment can appear only "
1779-
"at the start of the translation unit">;
1780-
def err_module_fragment_exported : Error<
1781-
"%select{global|private}0 module fragment cannot be exported">;
1782-
def err_private_module_fragment_expected_semi : Error<
1783-
"expected ';' after private module fragment declaration">;
1784-
def err_missing_before_module_end : Error<"expected %0 at end of module">;
1785-
def err_unsupported_module_partition : Error<
1786-
"module partitions are only supported for C++20 onwards">;
1787-
def err_import_not_allowed_here : Error<
1788-
"imports must immediately follow the module declaration">;
1789-
def err_partition_import_outside_module : Error<
1790-
"module partition imports must be within a module purview">;
1791-
def err_import_in_wrong_fragment : Error<
1792-
"module%select{| partition}0 imports cannot be in the %select{global|private}1 module fragment">;
1793-
1794-
def err_export_empty : Error<"export declaration cannot be empty">;
1763+
def err_unexpected_module_import_decl
1764+
: Error<"%select{module|import}0 declaration can only appear at the top "
1765+
"level">;
1766+
def err_module_expected_ident
1767+
: Error<"expected a module name after '%select{module|import}0'">;
1768+
def err_attribute_not_module_attr
1769+
: Error<"%0 attribute cannot be applied to a module">;
1770+
def err_keyword_not_module_attr : Error<"%0 cannot be applied to a module">;
1771+
def err_attribute_not_import_attr
1772+
: Error<"%0 attribute cannot be applied to a module import">;
1773+
def err_keyword_not_import_attr
1774+
: Error<"%0 cannot be applied to a module import">;
1775+
def err_module_expected_semi : Error<"expected ';' after module name">;
1776+
def err_global_module_introducer_not_at_start
1777+
: Error<"'module;' introducing a global module fragment can appear only "
1778+
"at the start of the translation unit">;
1779+
def err_module_fragment_exported
1780+
: Error<"%select{global|private}0 module fragment cannot be exported">;
1781+
def err_private_module_fragment_expected_semi
1782+
: Error<"expected ';' after private module fragment declaration">;
1783+
def err_missing_before_module_end : Error<"expected %0 at end of module">;
1784+
def err_import_not_allowed_here
1785+
: Error<"imports must immediately follow the module declaration">;
1786+
def err_partition_import_outside_module
1787+
: Error<"module partition imports must be within a module purview">;
1788+
def err_import_in_wrong_fragment
1789+
: Error<"module%select{| partition}0 imports cannot be in the "
1790+
"%select{global|private}1 module fragment">;
1791+
1792+
def err_export_empty : Error<"export declaration cannot be empty">;
17951793
}
17961794

17971795
let CategoryName = "Generics Issue" in {

clang/include/clang/Basic/IdentifierTable.h

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
179179
LLVM_PREFERRED_TYPE(bool)
180180
unsigned IsModulesImport : 1;
181181

182+
// True if this is the 'module' contextual keyword.
183+
LLVM_PREFERRED_TYPE(bool)
184+
unsigned IsModulesDecl : 1;
185+
182186
// True if this is a mangled OpenMP variant name.
183187
LLVM_PREFERRED_TYPE(bool)
184188
unsigned IsMangledOpenMPVariantName : 1;
@@ -215,8 +219,9 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
215219
IsCPPOperatorKeyword(false), NeedsHandleIdentifier(false),
216220
IsFromAST(false), ChangedAfterLoad(false), FEChangedAfterLoad(false),
217221
RevertedTokenID(false), OutOfDate(false), IsModulesImport(false),
218-
IsMangledOpenMPVariantName(false), IsDeprecatedMacro(false),
219-
IsRestrictExpansion(false), IsFinal(false), IsKeywordInCpp(false) {}
222+
IsModulesDecl(false), IsMangledOpenMPVariantName(false),
223+
IsDeprecatedMacro(false), IsRestrictExpansion(false), IsFinal(false),
224+
IsKeywordInCpp(false) {}
220225

221226
public:
222227
IdentifierInfo(const IdentifierInfo &) = delete;
@@ -528,6 +533,18 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
528533
RecomputeNeedsHandleIdentifier();
529534
}
530535

536+
/// Determine whether this is the contextual keyword \c module.
537+
bool isModulesDeclaration() const { return IsModulesDecl; }
538+
539+
/// Set whether this identifier is the contextual keyword \c module.
540+
void setModulesDeclaration(bool I) {
541+
IsModulesDecl = I;
542+
if (I)
543+
NeedsHandleIdentifier = true;
544+
else
545+
RecomputeNeedsHandleIdentifier();
546+
}
547+
531548
/// Determine whether this is the mangled name of an OpenMP variant.
532549
bool isMangledOpenMPVariantName() const { return IsMangledOpenMPVariantName; }
533550

@@ -745,10 +762,11 @@ class IdentifierTable {
745762
// contents.
746763
II->Entry = &Entry;
747764

748-
// If this is the 'import' contextual keyword, mark it as such.
765+
// If this is the 'import' or 'module' contextual keyword, mark it as such.
749766
if (Name == "import")
750767
II->setModulesImport(true);
751-
768+
else if (Name == "module")
769+
II->setModulesDeclaration(true);
752770
return *II;
753771
}
754772

clang/include/clang/Basic/TokenKinds.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ PPKEYWORD(pragma)
133133
// C23 & C++26 #embed
134134
PPKEYWORD(embed)
135135

136+
// C++20 Module Directive
137+
PPKEYWORD(module)
138+
136139
// GNU Extensions.
137140
PPKEYWORD(import)
138141
PPKEYWORD(include_next)
@@ -1023,6 +1026,9 @@ ANNOTATION(module_include)
10231026
ANNOTATION(module_begin)
10241027
ANNOTATION(module_end)
10251028

1029+
// Annotations for C++, Clang and Objective-C named modules.
1030+
ANNOTATION(module_name)
1031+
10261032
// Annotation for a header_name token that has been looked up and transformed
10271033
// into the name of a header unit.
10281034
ANNOTATION(header_unit)

clang/include/clang/Frontend/CompilerInstance.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -863,7 +863,7 @@ class CompilerInstance : public ModuleLoader {
863863
/// load it.
864864
ModuleLoadResult findOrCompileModuleAndReadAST(StringRef ModuleName,
865865
SourceLocation ImportLoc,
866-
SourceLocation ModuleNameLoc,
866+
SourceRange ModuleNameRange,
867867
bool IsInclusionDirective);
868868

869869
/// Creates a \c CompilerInstance for compiling a module.

clang/include/clang/Lex/CodeCompletionHandler.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@
1313
#ifndef LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
1414
#define LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
1515

16+
#include "clang/Basic/IdentifierTable.h"
17+
#include "clang/Basic/SourceLocation.h"
1618
#include "llvm/ADT/StringRef.h"
1719

1820
namespace clang {
1921

2022
class IdentifierInfo;
2123
class MacroInfo;
24+
using ModuleIdPath = ArrayRef<IdentifierLoc>;
2225

2326
/// Callback handler that receives notifications when performing code
2427
/// completion within the preprocessor.
@@ -70,6 +73,11 @@ class CodeCompletionHandler {
7073
/// file where we expect natural language, e.g., a comment, string, or
7174
/// \#error directive.
7275
virtual void CodeCompleteNaturalLanguage() { }
76+
77+
/// Callback invoked when performing code completion inside the module name
78+
/// part of an import directive.
79+
virtual void CodeCompleteModuleImport(SourceLocation ImportLoc,
80+
ModuleIdPath Path) {}
7381
};
7482

7583
}

0 commit comments

Comments
 (0)