diff options
author | Alex Lorenz <arphaman@gmail.com> | 2022-05-19 16:09:36 -0700 |
---|---|---|
committer | Alex Lorenz <arphaman@gmail.com> | 2022-05-24 10:02:53 -0700 |
commit | ee8524087c78a673fcf5486ded69ee597a85e0f1 (patch) | |
tree | 9571f951fb4a2cbca8ff3649f7aff6718a1ad550 /clang/tools | |
parent | efebb27b745a0d677ad2ea9aefff242c12aef29c (diff) | |
download | llvm-ee8524087c78a673fcf5486ded69ee597a85e0f1.zip llvm-ee8524087c78a673fcf5486ded69ee597a85e0f1.tar.gz llvm-ee8524087c78a673fcf5486ded69ee597a85e0f1.tar.bz2 |
[libclang] add supporting for indexing/visiting C++ concepts
This commit builds upon recently added indexing support for C++ concepts
from https://reviews.llvm.org/D124441 by extending libclang to
support indexing and visiting concepts, constraints and requires
expressions as well.
Differential Revision: https://reviews.llvm.org/D126031
Diffstat (limited to 'clang/tools')
-rw-r--r-- | clang/tools/c-index-test/c-index-test.c | 2 | ||||
-rw-r--r-- | clang/tools/libclang/CIndex.cpp | 141 | ||||
-rw-r--r-- | clang/tools/libclang/CXCursor.cpp | 10 | ||||
-rw-r--r-- | clang/tools/libclang/CXIndexDataConsumer.cpp | 14 | ||||
-rw-r--r-- | clang/tools/libclang/CXIndexDataConsumer.h | 2 | ||||
-rw-r--r-- | clang/tools/libclang/CursorVisitor.h | 9 |
6 files changed, 172 insertions, 6 deletions
diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c index 7d0d6e8..8eac69d 100644 --- a/clang/tools/c-index-test/c-index-test.c +++ b/clang/tools/c-index-test/c-index-test.c @@ -3504,6 +3504,8 @@ static const char *getEntityKindString(CXIdxEntityKind kind) { case CXIdxEntity_CXXConversionFunction: return "conversion-func"; case CXIdxEntity_CXXTypeAlias: return "type-alias"; case CXIdxEntity_CXXInterface: return "c++-__interface"; + case CXIdxEntity_CXXConcept: + return "concept"; } assert(0 && "Garbage entity kind"); return 0; diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 235ca3e..97ce1c7 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -761,10 +761,10 @@ bool CursorVisitor::VisitClassTemplatePartialSpecializationDecl( } bool CursorVisitor::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { - if (const auto *TC = D->getTypeConstraint()) - if (Visit(MakeCXCursor(TC->getImmediatelyDeclaredConstraint(), StmtParent, - TU, RegionOfInterest))) + if (const auto *TC = D->getTypeConstraint()) { + if (VisitTypeConstraint(*TC)) return true; + } // Visit the default argument. if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) @@ -863,6 +863,11 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) { // FIXME: Attributes? } + if (auto *E = ND->getTrailingRequiresClause()) { + if (Visit(E)) + return true; + } + if (ND->doesThisDeclarationHaveABody() && !ND->isLateTemplateParsed()) { if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ND)) { // Find the initializers that were written in the source. @@ -1310,6 +1315,75 @@ bool CursorVisitor::VisitDecompositionDecl(DecompositionDecl *D) { return VisitVarDecl(D); } +bool CursorVisitor::VisitConceptDecl(ConceptDecl *D) { + if (VisitTemplateParameters(D->getTemplateParameters())) + return true; + + if (auto *E = D->getConstraintExpr()) { + if (Visit(MakeCXCursor(E, D, TU, RegionOfInterest))) + return true; + } + return false; +} + +bool CursorVisitor::VisitTypeConstraint(const TypeConstraint &TC) { + if (TC.getNestedNameSpecifierLoc()) { + if (VisitNestedNameSpecifierLoc(TC.getNestedNameSpecifierLoc())) + return true; + } + if (TC.getNamedConcept()) { + if (Visit(MakeCursorTemplateRef(TC.getNamedConcept(), + TC.getConceptNameLoc(), TU))) + return true; + } + if (auto Args = TC.getTemplateArgsAsWritten()) { + for (const auto &Arg : Args->arguments()) { + if (VisitTemplateArgumentLoc(Arg)) + return true; + } + } + return false; +} + +bool CursorVisitor::VisitConceptRequirement(const concepts::Requirement &R) { + using namespace concepts; + switch (R.getKind()) { + case Requirement::RK_Type: { + const TypeRequirement &TR = cast<TypeRequirement>(R); + if (!TR.isSubstitutionFailure()) { + if (Visit(TR.getType()->getTypeLoc())) + return true; + } + break; + } + case Requirement::RK_Simple: + case Requirement::RK_Compound: { + const ExprRequirement &ER = cast<ExprRequirement>(R); + if (!ER.isExprSubstitutionFailure()) { + if (Visit(ER.getExpr())) + return true; + } + if (ER.getKind() == Requirement::RK_Compound) { + const auto &RTR = ER.getReturnTypeRequirement(); + if (RTR.isTypeConstraint()) { + if (const auto *Cons = RTR.getTypeConstraint()) + VisitTypeConstraint(*Cons); + } + } + break; + } + case Requirement::RK_Nested: { + const NestedRequirement &NR = cast<NestedRequirement>(R); + if (!NR.isSubstitutionFailure()) { + if (Visit(NR.getConstraintExpr())) + return true; + } + break; + } + } + return false; +} + bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) { switch (Name.getName().getNameKind()) { case clang::DeclarationName::Identifier: @@ -1436,6 +1510,12 @@ bool CursorVisitor::VisitTemplateParameters( return true; } + if (const auto *E = Params->getRequiresClause()) { + if (Visit(MakeCXCursor(Params->getRequiresClause(), nullptr, TU, + RegionOfInterest))) + return true; + } + return false; } @@ -1594,6 +1674,11 @@ bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) { } bool CursorVisitor::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { + if (const auto *TC = TL.getDecl()->getTypeConstraint()) { + if (VisitTypeConstraint(*TC)) + return true; + } + return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU)); } @@ -1869,6 +1954,9 @@ DEF_JOB(DeclRefExprParts, DeclRefExpr, DeclRefExprPartsKind) DEF_JOB(OverloadExprParts, OverloadExpr, OverloadExprPartsKind) DEF_JOB(SizeOfPackExprParts, SizeOfPackExpr, SizeOfPackExprPartsKind) DEF_JOB(LambdaExprParts, LambdaExpr, LambdaExprPartsKind) +DEF_JOB(ConceptSpecializationExprVisit, ConceptSpecializationExpr, + ConceptSpecializationExprVisitKind) +DEF_JOB(RequiresExprVisit, RequiresExpr, RequiresExprVisitKind) DEF_JOB(PostChildrenVisit, void, PostChildrenVisitKind) #undef DEF_JOB @@ -2044,6 +2132,8 @@ public: void VisitPseudoObjectExpr(const PseudoObjectExpr *E); void VisitOpaqueValueExpr(const OpaqueValueExpr *E); void VisitLambdaExpr(const LambdaExpr *E); + void VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E); + void VisitRequiresExpr(const RequiresExpr *E); void VisitOMPExecutableDirective(const OMPExecutableDirective *D); void VisitOMPLoopBasedDirective(const OMPLoopBasedDirective *D); void VisitOMPLoopDirective(const OMPLoopDirective *D); @@ -2887,6 +2977,15 @@ void EnqueueVisitor::VisitLambdaExpr(const LambdaExpr *E) { AddStmt(E->getBody()); WL.push_back(LambdaExprParts(E, Parent)); } +void EnqueueVisitor::VisitConceptSpecializationExpr( + const ConceptSpecializationExpr *E) { + WL.push_back(ConceptSpecializationExprVisit(E, Parent)); +} +void EnqueueVisitor::VisitRequiresExpr(const RequiresExpr *E) { + WL.push_back(RequiresExprVisit(E, Parent)); + for (ParmVarDecl *VD : E->getLocalParameters()) + AddDecl(VD); +} void EnqueueVisitor::VisitPseudoObjectExpr(const PseudoObjectExpr *E) { // Treat the expression like its syntactic form. Visit(E->getSyntacticForm()); @@ -3380,6 +3479,36 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) { break; } + case VisitorJob::ConceptSpecializationExprVisitKind: { + const ConceptSpecializationExpr *E = + cast<ConceptSpecializationExprVisit>(&LI)->get(); + if (NestedNameSpecifierLoc QualifierLoc = + E->getNestedNameSpecifierLoc()) { + if (VisitNestedNameSpecifierLoc(QualifierLoc)) + return true; + } + + if (E->getNamedConcept() && + Visit(MakeCursorTemplateRef(E->getNamedConcept(), + E->getConceptNameLoc(), TU))) + return true; + + if (auto Args = E->getTemplateArgsAsWritten()) { + for (const auto &Arg : Args->arguments()) { + if (VisitTemplateArgumentLoc(Arg)) + return true; + } + } + break; + } + + case VisitorJob::RequiresExprVisitKind: { + const RequiresExpr *E = cast<RequiresExprVisit>(&LI)->get(); + for (const concepts::Requirement *R : E->getRequirements()) + VisitConceptRequirement(*R); + break; + } + case VisitorJob::PostChildrenVisitKind: if (PostChildrenVisitor(Parent, ClientData)) return true; @@ -5401,6 +5530,10 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return cxstring::createRef("ObjCMessageExpr"); case CXCursor_BuiltinBitCastExpr: return cxstring::createRef("BuiltinBitCastExpr"); + case CXCursor_ConceptSpecializationExpr: + return cxstring::createRef("ConceptSpecializationExpr"); + case CXCursor_RequiresExpr: + return cxstring::createRef("RequiresExpr"); case CXCursor_UnexposedStmt: return cxstring::createRef("UnexposedStmt"); case CXCursor_DeclStmt: @@ -5751,6 +5884,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return cxstring::createRef("attribute(warn_unused_result)"); case CXCursor_AlignedAttr: return cxstring::createRef("attribute(aligned)"); + case CXCursor_ConceptDecl: + return cxstring::createRef("ConceptDecl"); } llvm_unreachable("Unhandled CXCursorKind"); diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index fbe3051..1de76ab 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -299,8 +299,6 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::BinaryConditionalOperatorClass: case Stmt::TypeTraitExprClass: case Stmt::CoawaitExprClass: - case Stmt::ConceptSpecializationExprClass: - case Stmt::RequiresExprClass: case Stmt::DependentCoawaitExprClass: case Stmt::CoyieldExprClass: case Stmt::CXXBindTemporaryExprClass: @@ -637,6 +635,14 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, return getSelectorIdentifierCursor(SelectorIdIndex, C); } + case Stmt::ConceptSpecializationExprClass: + K = CXCursor_ConceptSpecializationExpr; + break; + + case Stmt::RequiresExprClass: + K = CXCursor_RequiresExpr; + break; + case Stmt::MSDependentExistsStmtClass: K = CXCursor_UnexposedStmt; break; diff --git a/clang/tools/libclang/CXIndexDataConsumer.cpp b/clang/tools/libclang/CXIndexDataConsumer.cpp index 2e87689..979acae 100644 --- a/clang/tools/libclang/CXIndexDataConsumer.cpp +++ b/clang/tools/libclang/CXIndexDataConsumer.cpp @@ -146,6 +146,11 @@ public: DataConsumer.importedModule(D); return true; } + + bool VisitConceptDecl(const ConceptDecl *D) { + DataConsumer.handleConcept(D); + return true; + } }; CXSymbolRole getSymbolRole(SymbolRoleSet Role) { @@ -883,6 +888,12 @@ bool CXIndexDataConsumer::handleTypeAliasTemplate(const TypeAliasTemplateDecl *D return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } +bool CXIndexDataConsumer::handleConcept(const ConceptDecl *D) { + DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(), + /*isDefinition=*/true, /*isContainer=*/false); + return handleDecl(D, D->getLocation(), getCursor(D), DInfo); +} + bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor, const NamedDecl *Parent, @@ -1249,7 +1260,6 @@ static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage case SymbolKind::TemplateTypeParm: case SymbolKind::TemplateTemplateParm: case SymbolKind::NonTypeTemplateParm: - case SymbolKind::Concept: return CXIdxEntity_Unexposed; case SymbolKind::Enum: return CXIdxEntity_Enum; @@ -1289,6 +1299,8 @@ static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage case SymbolKind::Destructor: return CXIdxEntity_CXXDestructor; case SymbolKind::ConversionFunction: return CXIdxEntity_CXXConversionFunction; case SymbolKind::Parameter: return CXIdxEntity_Variable; + case SymbolKind::Concept: + return CXIdxEntity_CXXConcept; } llvm_unreachable("invalid symbol kind"); } diff --git a/clang/tools/libclang/CXIndexDataConsumer.h b/clang/tools/libclang/CXIndexDataConsumer.h index f93b06c..04c64ca 100644 --- a/clang/tools/libclang/CXIndexDataConsumer.h +++ b/clang/tools/libclang/CXIndexDataConsumer.h @@ -409,6 +409,8 @@ public: bool handleFunctionTemplate(const FunctionTemplateDecl *D); bool handleTypeAliasTemplate(const TypeAliasTemplateDecl *D); + bool handleConcept(const ConceptDecl *D); + bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor, const NamedDecl *Parent, const DeclContext *DC, diff --git a/clang/tools/libclang/CursorVisitor.h b/clang/tools/libclang/CursorVisitor.h index 364d9fd..74190bd 100644 --- a/clang/tools/libclang/CursorVisitor.h +++ b/clang/tools/libclang/CursorVisitor.h @@ -19,6 +19,10 @@ namespace clang { class PreprocessingRecord; class ASTUnit; +namespace concepts { +class Requirement; +} + namespace cxcursor { class VisitorJob { @@ -37,6 +41,8 @@ public: MemberRefVisitKind, SizeOfPackExprPartsKind, LambdaExprPartsKind, + ConceptSpecializationExprVisitKind, + RequiresExprVisitKind, PostChildrenVisitKind }; @@ -242,6 +248,9 @@ public: bool VisitStaticAssertDecl(StaticAssertDecl *D); bool VisitFriendDecl(FriendDecl *D); bool VisitDecompositionDecl(DecompositionDecl *D); + bool VisitConceptDecl(ConceptDecl *D); + bool VisitTypeConstraint(const TypeConstraint &TC); + bool VisitConceptRequirement(const concepts::Requirement &R); // Name visitor bool VisitDeclarationNameInfo(DeclarationNameInfo Name); |