aboutsummaryrefslogtreecommitdiff
path: root/clang/tools
diff options
context:
space:
mode:
authorAlex Lorenz <arphaman@gmail.com>2022-05-19 16:09:36 -0700
committerAlex Lorenz <arphaman@gmail.com>2022-05-24 10:02:53 -0700
commitee8524087c78a673fcf5486ded69ee597a85e0f1 (patch)
tree9571f951fb4a2cbca8ff3649f7aff6718a1ad550 /clang/tools
parentefebb27b745a0d677ad2ea9aefff242c12aef29c (diff)
downloadllvm-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.c2
-rw-r--r--clang/tools/libclang/CIndex.cpp141
-rw-r--r--clang/tools/libclang/CXCursor.cpp10
-rw-r--r--clang/tools/libclang/CXIndexDataConsumer.cpp14
-rw-r--r--clang/tools/libclang/CXIndexDataConsumer.h2
-rw-r--r--clang/tools/libclang/CursorVisitor.h9
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);