[clang] [clang-tools-extra] feat: highlight for import, export keyword of CXX Module (PR #204511)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 17 22:48:07 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-modules
Author: Access (Decodetalkers)
<details>
<summary>Changes</summary>
This pr aims to add highlight for import and export keyword And induced new SemanticHighlight `keyword`
---
Patch is 48.61 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/204511.diff
11 Files Affected:
- (modified) clang-tools-extra/clangd/FindTarget.cpp (+12-1)
- (modified) clang-tools-extra/clangd/SemanticHighlighting.cpp (+6-1)
- (modified) clang-tools-extra/clangd/SemanticHighlighting.h (+1)
- (modified) clang/include/clang/AST/Decl.h (+45-13)
- (modified) clang/include/clang/Parse/Parser.h (+2-1)
- (modified) clang/include/clang/Sema/Sema.h (+17-10)
- (modified) clang/lib/AST/Decl.cpp (+36-34)
- (modified) clang/lib/Parse/ParseDeclCXX.cpp (+7-4)
- (modified) clang/lib/Parse/Parser.cpp (+43-36)
- (modified) clang/lib/Sema/SemaLookup.cpp (+10-9)
- (modified) clang/lib/Sema/SemaModule.cpp (+43-31)
``````````diff
diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp
index 41c9cddfebbbc..4ac77a884c70b 100644
--- a/clang-tools-extra/clangd/FindTarget.cpp
+++ b/clang-tools-extra/clangd/FindTarget.cpp
@@ -619,7 +619,18 @@ llvm::SmallVector<ReferenceLoc> refInDecl(const Decl *D,
/*IsDecl=*/false,
{D->getNominatedNamespaceAsWritten()}});
}
-
+ void VisitImportDecl(const ImportDecl *D) {
+ Refs.push_back(ReferenceLoc{D->getQualifierLoc(),
+ D->getIdentLocation(),
+ /*IsDecl=*/true,
+ {D}});
+ }
+ void VisitExportDecl(const ExportDecl *D) {
+ Refs.push_back(ReferenceLoc{D->getQualifierLoc(),
+ D->getIdentLocation(),
+ /*IsDecl=*/true,
+ {D}});
+ }
void VisitUsingDecl(const UsingDecl *D) {
// "using ns::identifier;" is a non-declaration reference.
Refs.push_back(ReferenceLoc{
diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp
index 856904bc810d1..5c331df5197bb 100644
--- a/clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -122,6 +122,8 @@ std::optional<HighlightingKind> kindForDecl(const NamedDecl *D,
: HighlightingKind::Method;
if (isa<FieldDecl, IndirectFieldDecl, ObjCPropertyDecl>(D))
return HighlightingKind::Field;
+ if (isa<ImportDecl, ExportDecl>(D))
+ return HighlightingKind::Keyword;
if (isa<EnumDecl>(D))
return HighlightingKind::Enum;
if (isa<EnumConstantDecl>(D))
@@ -176,7 +178,7 @@ std::optional<HighlightingKind> kindForType(const Type *TP,
}
bool isDependent(const Decl *D) {
- if (isa<UnresolvedUsingValueDecl>(D))
+ if (isa<UnresolvedUsingValueDecl, ImportDecl>(D))
return true;
return false;
}
@@ -1244,6 +1246,7 @@ bool operator<(const HighlightingToken &L, const HighlightingToken &R) {
std::tie(R.R, R.Kind, R.Modifiers);
}
+// FIXME: import module
std::vector<SemanticToken>
toSemanticTokens(llvm::ArrayRef<HighlightingToken> Tokens,
llvm::StringRef Code) {
@@ -1323,6 +1326,8 @@ llvm::StringRef toSemanticTokenType(HighlightingKind Kind) {
return "function";
case HighlightingKind::Method:
return "method";
+ case HighlightingKind::Keyword:
+ return "keyword";
case HighlightingKind::StaticMethod:
// FIXME: better method with static modifier?
return "function";
diff --git a/clang-tools-extra/clangd/SemanticHighlighting.h b/clang-tools-extra/clangd/SemanticHighlighting.h
index 59d742b83ee52..3b1c12418becb 100644
--- a/clang-tools-extra/clangd/SemanticHighlighting.h
+++ b/clang-tools-extra/clangd/SemanticHighlighting.h
@@ -34,6 +34,7 @@ enum class HighlightingKind {
Parameter,
Function,
Method,
+ Keyword,
StaticMethod,
Field,
StaticField,
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index e3f513732e588..46635bc1b86a1 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -5055,7 +5055,7 @@ class CapturedDecl final
///
/// Import declarations can also be implicitly generated from
/// \#include/\#import directives.
-class ImportDecl final : public Decl,
+class ImportDecl final : public NamedDecl,
llvm::TrailingObjects<ImportDecl, SourceLocation> {
friend class ASTContext;
friend class ASTDeclReader;
@@ -5065,6 +5065,7 @@ class ImportDecl final : public Decl,
/// The imported module.
Module *ImportedModule = nullptr;
+ NestedNameSpecifierLoc QualifierLoc;
/// The next import in the list of imports local to the translation
/// unit being parsed (not loaded from an AST file).
///
@@ -5076,12 +5077,15 @@ class ImportDecl final : public Decl,
llvm::PointerIntPair<ImportDecl *, 1, bool> NextLocalImportAndComplete;
ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported,
+ NestedNameSpecifierLoc QualifierLoc, IdentifierInfo *Id,
ArrayRef<SourceLocation> IdentifierLocs);
ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported,
+ NestedNameSpecifierLoc QualifierLoc, DeclarationName Id,
SourceLocation EndLoc);
- ImportDecl(EmptyShell Empty) : Decl(Import, Empty) {}
+ ImportDecl(EmptyShell Empty)
+ : NamedDecl(Import, nullptr, SourceLocation(), DeclarationName()) {}
bool isImportComplete() const { return NextLocalImportAndComplete.getInt(); }
@@ -5100,14 +5104,17 @@ class ImportDecl final : public Decl,
public:
/// Create a new module import declaration.
static ImportDecl *Create(ASTContext &C, DeclContext *DC,
+ NestedNameSpecifierLoc QualifierLoc,
SourceLocation StartLoc, Module *Imported,
+ IdentifierInfo *Id,
ArrayRef<SourceLocation> IdentifierLocs);
/// Create a new module import declaration for an implicitly-generated
/// import.
static ImportDecl *CreateImplicit(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, Module *Imported,
- SourceLocation EndLoc);
+ NestedNameSpecifierLoc QualifierLoc,
+ DeclarationName Id, SourceLocation EndLoc);
/// Create a new, deserialized module import declaration.
static ImportDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
@@ -5116,6 +5123,18 @@ class ImportDecl final : public Decl,
/// Retrieve the module that was imported by the import declaration.
Module *getImportedModule() const { return ImportedModule; }
+ /// Retrieve the nested-name-specifier that qualifies the
+ /// name of the namespace, with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ /// Retrieve the nested-name-specifier that qualifies the
+ /// name of the namespace.
+ NestedNameSpecifier getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
+
+ SourceLocation getIdentLocation() const { return getLocation(); }
+
/// Retrieves the locations of each of the identifiers that make up
/// the complete module name in the import declaration.
///
@@ -5135,22 +5154,26 @@ class ImportDecl final : public Decl,
/// \code
/// export void foo();
/// \endcode
-class ExportDecl final : public Decl, public DeclContext {
- LLVM_DECLARE_VIRTUAL_ANCHOR_FUNCTION();
+class ExportDecl final : public NamedDecl, public DeclContext {
+ void anchor() override;
private:
friend class ASTDeclReader;
/// The source location for the right brace (if valid).
SourceLocation RBraceLoc;
+ NestedNameSpecifierLoc QualifierLoc;
- ExportDecl(DeclContext *DC, SourceLocation ExportLoc)
- : Decl(Export, DC, ExportLoc), DeclContext(Export),
- RBraceLoc(SourceLocation()) {}
+ ExportDecl(DeclContext *DC, SourceLocation ExportLoc, NestedNameSpecifierLoc QualifierLoc, DeclarationName Id)
+ : NamedDecl(Export, DC, ExportLoc, Id), DeclContext(Export),
+ RBraceLoc(SourceLocation()),
+ QualifierLoc(QualifierLoc){}
public:
static ExportDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation ExportLoc);
+ SourceLocation ExportLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ DeclarationName Id);
static ExportDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
SourceLocation getExportLoc() const { return getLocation(); }
@@ -5170,14 +5193,24 @@ class ExportDecl final : public Decl, public DeclContext {
SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(getLocation(), getEndLoc());
}
+ /// Retrieve the nested-name-specifier that qualifies the
+ /// name of the namespace, with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ /// Retrieve the nested-name-specifier that qualifies the
+ /// name of the namespace.
+ NestedNameSpecifier getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
+ SourceLocation getIdentLocation() const { return getLocation(); }
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Export; }
static DeclContext *castToDeclContext(const ExportDecl *D) {
- return static_cast<DeclContext *>(const_cast<ExportDecl*>(D));
+ return static_cast<DeclContext *>(const_cast<ExportDecl *>(D));
}
static ExportDecl *castFromDeclContext(const DeclContext *DC) {
- return static_cast<ExportDecl *>(const_cast<DeclContext*>(DC));
+ return static_cast<ExportDecl *>(const_cast<DeclContext *>(DC));
}
};
@@ -5188,8 +5221,7 @@ class EmptyDecl : public Decl {
virtual void anchor();
public:
- static EmptyDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L);
+ static EmptyDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L);
static EmptyDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 5e7af97feeb6c..04d39642d6c23 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -7656,7 +7656,8 @@ class Parser : public CodeCompletionHandler {
///
/// exception-declaration:
/// attribute-specifier-seq[opt] type-specifier-seq declarator
- /// attribute-specifier-seq[opt] type-specifier-seq abstract-declarator[opt]
+ /// attribute-specifier-seq[opt] type-specifier-seq
+ /// abstract-declarator[opt]
/// '...'
/// \endverbatim
///
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index ff474fdd99562..89c75b6fdebfc 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9985,10 +9985,11 @@ class Sema final : public SemaBase {
/// The parser has processed a module-declaration that begins the definition
/// of a module interface or implementation.
- DeclGroupPtrTy ActOnModuleDecl(SourceLocation StartLoc,
+ DeclGroupPtrTy ActOnModuleDecl(CXXScopeSpec *SS, SourceLocation StartLoc,
SourceLocation ModuleLoc, ModuleDeclKind MDK,
ModuleIdPath Path, ModuleIdPath Partition,
ModuleImportState &ImportState,
+ IdentifierInfo *Id,
bool SeenNoTrivialPPDirective);
/// The parser has processed a global-module-fragment declaration that begins
@@ -10011,24 +10012,27 @@ class Sema final : public SemaBase {
/// \param ImportLoc The location of the 'import' keyword.
/// \param Path The module toplevel name as an access path.
/// \param IsPartition If the name is for a partition.
- DeclResult ActOnModuleImport(SourceLocation StartLoc,
+ DeclResult ActOnModuleImport(CXXScopeSpec *SS, SourceLocation StartLoc,
SourceLocation ExportLoc,
SourceLocation ImportLoc, ModuleIdPath Path,
- bool IsPartition = false);
- DeclResult ActOnModuleImport(SourceLocation StartLoc,
+ IdentifierInfo *Id, bool IsPartition = false);
+ DeclResult ActOnModuleImport(CXXScopeSpec *SS, SourceLocation StartLoc,
SourceLocation ExportLoc,
SourceLocation ImportLoc, Module *M,
- ModuleIdPath Path = {});
+ IdentifierInfo *Id, ModuleIdPath Path = {});
/// The parser has processed a module import translated from a
/// #include or similar preprocessing directive.
- void ActOnAnnotModuleInclude(SourceLocation DirectiveLoc, Module *Mod);
- void BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod);
+ void ActOnAnnotModuleInclude(CXXScopeSpec *SS, SourceLocation DirectiveLoc,
+ IdentifierInfo *Id, Module *Mod);
+ void BuildModuleInclude(CXXScopeSpec *SS, SourceLocation DirectiveLoc,
+ IdentifierInfo *Id, Module *Mod);
/// The parsed has entered a submodule.
void ActOnAnnotModuleBegin(SourceLocation DirectiveLoc, Module *Mod);
/// The parser has left a submodule.
- void ActOnAnnotModuleEnd(SourceLocation DirectiveLoc, Module *Mod);
+ void ActOnAnnotModuleEnd(CXXScopeSpec *SS, SourceLocation DirectiveLoc,
+ IdentifierInfo *Id, Module *Mod);
/// Create an implicit import of the given module at the given
/// source location, for error recovery, if possible.
@@ -10036,12 +10040,15 @@ class Sema final : public SemaBase {
/// This routine is typically used when an entity found by name lookup
/// is actually hidden within a module that we know about but the user
/// has forgotten to import.
- void createImplicitModuleImportForErrorRecovery(SourceLocation Loc,
+ void createImplicitModuleImportForErrorRecovery(CXXScopeSpec *SS,
+ SourceLocation Loc,
+ DeclarationName Id,
Module *Mod);
/// We have parsed the start of an export declaration, including the '{'
/// (if present).
- Decl *ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc,
+ Decl *ActOnStartExportDecl(Scope *S, CXXScopeSpec *SS,
+ SourceLocation ExportLoc, IdentifierInfo *Id,
SourceLocation LBraceLoc);
/// Complete the definition of an export declaration.
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index a6de9959e0f62..fbab744624692 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -394,8 +394,7 @@ void LinkageComputer::mergeTemplateLV(
LinkageInfo &LV, const FunctionDecl *fn,
const FunctionTemplateSpecializationInfo *specInfo,
LVComputationKind computation) {
- bool considerVisibility =
- shouldConsiderTemplateVisibility(fn, specInfo);
+ bool considerVisibility = shouldConsiderTemplateVisibility(fn, specInfo);
FunctionTemplateDecl *temp = specInfo->getTemplate();
// Merge information from the template declaration.
@@ -705,10 +704,10 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
// If we're declared in a namespace with a visibility attribute,
// use that namespace's visibility, and it still counts as explicit.
for (const DeclContext *DC = D->getDeclContext();
- !isa<TranslationUnitDecl>(DC);
- DC = DC->getParent()) {
+ !isa<TranslationUnitDecl>(DC); DC = DC->getParent()) {
const auto *ND = dyn_cast<NamespaceDecl>(DC);
- if (!ND) continue;
+ if (!ND)
+ continue;
if (std::optional<Visibility> Vis =
getExplicitVisibility(ND, computation)) {
LV.mergeVisibility(*Vis, true);
@@ -962,7 +961,6 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D,
if (!isExternallyVisible(classLV.getLinkage()))
return classLV;
-
// Otherwise, don't merge in classLV yet, because in certain cases
// we need to completely ignore the visibility from it.
@@ -2178,7 +2176,7 @@ SourceRange VarDecl::getSourceRange() const {
return DeclaratorDecl::getSourceRange();
}
-template<typename T>
+template <typename T>
static LanguageLinkage getDeclLanguageLinkage(const T &D) {
// C++ [dcl.link]p1: All function types, function names with external linkage,
// and variable names with external linkage have a language linkage.
@@ -2205,8 +2203,7 @@ static LanguageLinkage getDeclLanguageLinkage(const T &D) {
return CXXLanguageLinkage;
}
-template<typename T>
-static bool isDeclExternC(const T &D) {
+template <typename T> static bool isDeclExternC(const T &D) {
// Since the context is ignored for class members, they can only have C++
// language linkage or no language linkage.
const DeclContext *DC = D.getDeclContext();
@@ -2863,8 +2860,8 @@ MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const {
return nullptr;
}
-void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
- SourceLocation PointOfInstantiation) {
+void VarDecl::setTemplateSpecializationKind(
+ TemplateSpecializationKind TSK, SourceLocation PointOfInstantiation) {
assert((isa<VarTemplateSpecializationDecl>(this) ||
getMemberSpecializationInfo()) &&
"not a variable or static data member template specialization");
@@ -2872,8 +2869,7 @@ void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
if (VarTemplateSpecializationDecl *Spec =
dyn_cast<VarTemplateSpecializationDecl>(this)) {
Spec->setSpecializationKind(TSK);
- if (TSK != TSK_ExplicitSpecialization &&
- PointOfInstantiation.isValid() &&
+ if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() &&
Spec->getPointOfInstantiation().isInvalid()) {
Spec->setPointOfInstantiation(PointOfInstantiation);
if (ASTMutationListener *L = getASTContext().getASTMutationListener())
@@ -2934,8 +2930,8 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
const IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, StorageClass S,
Expr *DefArg) {
- return new (C, DC) ParmVarDecl(ParmVar, C, DC, StartLoc, IdLoc, Id, T, TInfo,
- S, DefArg);
+ return new (C, DC)
+ ParmVarDecl(ParmVar, C, DC, StartLoc, IdLoc, Id, T, TInfo, S, DefArg);
}
QualType ParmVarDecl::getOriginalType() const {
@@ -3590,9 +3586,7 @@ LanguageLinkage FunctionDecl::getLanguageLinkage() const {
return getDeclLanguageLinkage(*this);
}
-bool FunctionDecl::isExternC() const {
- return isDeclExternC(*this);
-}
+bool FunctionDecl::isExternC() const { return isDeclExternC(*this); }
bool FunctionDecl::isInExternCContext() const {
if (DeviceKernelAttr::isOpenCLSpelling(getAttr<DeviceKernelAttr>()))
@@ -3611,8 +3605,7 @@ bool FunctionDecl::isGlobal() const {
if (getCanonicalDecl()->getStorageClass() == SC_Static)
return false;
- for (const DeclContext *DC = getDeclContext();
- DC->isNamespace();
+ for (const DeclContext *DC = getDeclContext(); DC->isNamespace();
DC = DC->getParent()) {
if (const auto *Namespace = cast<NamespaceDecl>(DC)) {
if (!Namespace->getDeclName())
@@ -3810,7 +3803,7 @@ void FunctionDecl::setParams(ASTContext &C,
// Zero params -> null pointer.
if (!NewParamInfo.empty()) {
- ParamInfo = new (C) ParmVarDecl*[NewParamInfo.size()];
+ ParamInfo = new (C) ParmVarDecl *[NewParamInfo.size()];
llvm::copy(NewParamInfo, ParamInfo);
}
}
@@ -4929,7 +4922,7 @@ void TagDecl::startDefinition() {
if (auto *D = dyn_cast<CXXRecordDecl>(this)) {
struct CXXRecordDecl::DefinitionData *Data =
- new (getASTContext()) struct CXXRecordDecl::DefinitionData(D);
+ new (getASTContext()) struct CXXRecordDecl::DefinitionData(D);
for (auto *I : redecls())
cast<CXXRecordDecl>(I)->DefinitionData = Data;
}
@@ -5470,7 +5463,7 @@ void BlockDecl::setParams(ArrayRef<ParmVarDecl *> NewParamInfo) {
// Zero params -> null pointer.
if (!NewParamInfo.empty()) {
NumParams = NewParamInfo.size();
- ParamInfo = new (getASTContext()) ParmVarDecl*[NewParamInfo.size()];
+ ParamInfo = new (getASTContext()) ParmVarDecl *[NewParamInfo.size()];
llvm::copy(NewParamInfo, ParamInfo);
}
}
@@ -6053,36 +6046,42 @@ static unsigned getNumModuleIdentifiers(Module *Mod) {
}
ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
- Module *Imported,
+ ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/204511
More information about the cfe-commits
mailing list