[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
This commit is contained in:
Alex Lorenz
2022-05-19 16:09:36 -07:00
parent efebb27b74
commit ee8524087c
10 changed files with 389 additions and 9 deletions

View File

@@ -2189,7 +2189,17 @@ enum CXCursorKind {
*/
CXCursor_CXXAddrspaceCastExpr = 152,
CXCursor_LastExpr = CXCursor_CXXAddrspaceCastExpr,
/**
* Expression that references a C++20 concept.
*/
CXCursor_ConceptSpecializationExpr = 153,
/**
* Expression that references a C++20 concept.
*/
CXCursor_RequiresExpr = 154,
CXCursor_LastExpr = CXCursor_RequiresExpr,
/* Statements */
CXCursor_FirstStmt = 200,
@@ -2700,8 +2710,13 @@ enum CXCursorKind {
* a friend declaration.
*/
CXCursor_FriendDecl = 603,
/**
* a concept declaration.
*/
CXCursor_ConceptDecl = 604,
CXCursor_FirstExtraDecl = CXCursor_ModuleImportDecl,
CXCursor_LastExtraDecl = CXCursor_FriendDecl,
CXCursor_LastExtraDecl = CXCursor_ConceptDecl,
/**
* A code completion overload candidate.
@@ -6319,7 +6334,8 @@ typedef enum {
CXIdxEntity_CXXDestructor = 23,
CXIdxEntity_CXXConversionFunction = 24,
CXIdxEntity_CXXTypeAlias = 25,
CXIdxEntity_CXXInterface = 26
CXIdxEntity_CXXInterface = 26,
CXIdxEntity_CXXConcept = 27
} CXIdxEntityKind;

View File

@@ -4044,6 +4044,9 @@ CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
case Decl::ObjCTypeParam:
return CXCursor_TemplateTypeParameter;
case Decl::Concept:
return CXCursor_ConceptDecl;
default:
if (const auto *TD = dyn_cast<TagDecl>(D)) {
switch (TD->getTagKind()) {

View File

@@ -0,0 +1,9 @@
// RUN: c-index-test -index-file %s -std=gnu++20 | FileCheck %s
template <typename T>
concept LargeType = sizeof(T) > 8;
// CHECK: [indexDeclaration]: kind: concept | name: LargeType | USR: c:@CT@LargeType | lang: C | cursor: ConceptDecl=LargeType:[[@LINE-1]]:9 (Definition) | loc: [[@LINE-1]]:9 | semantic-container: [TU] | lexical-container: [TU] | isRedecl: 0 | isDef: 1 | isContainer: 0 | isImplicit: 0
template <LargeType T>
// CHECK: [indexEntityReference]: kind: concept | name: LargeType | USR: c:@CT@LargeType | lang: C | cursor: TemplateRef=LargeType:4:9 | loc: [[@LINE-1]]:11 | <parent>:: kind: function-template | name: f | USR: c:@FT@>1#Tf#v# | lang: C++ | container: [<<NULL>>] | refkind: direct | role: ref
void f();

View File

@@ -0,0 +1,186 @@
// RUN: c-index-test -test-load-source all %s -std=gnu++20 -fno-delayed-template-parsing | FileCheck %s
template<class T>
struct type_trait {
const static bool value = false;
};
template<>
struct type_trait<int> {
const static bool value = true;
};
template <class T>
requires (type_trait<T>::value)
// CHECK: index-concepts.cpp:[[@LINE-1]]:10: ParenExpr= Extent=[[[@LINE-1]]:10 - [[@LINE-1]]:32]
// CHECK: index-concepts.cpp:[[@LINE-2]]:11: DeclRefExpr= Extent=[[[@LINE-2]]:11 - [[@LINE-2]]:31]
// CHECK: index-concepts.cpp:[[@LINE-3]]:11: TemplateRef=type_trait:4:8 Extent=[[[@LINE-3]]:11 - [[@LINE-3]]:21]
// CHECK: index-concepts.cpp:[[@LINE-4]]:22: TypeRef=T:13:17 Extent=[[[@LINE-4]]:22 - [[@LINE-4]]:23]
void indexRequiresClause() {
}
template<class T>
requires (type_trait<T>::value)
// CHECK: index-concepts.cpp:[[@LINE-1]]:10: ParenExpr= Extent=[[[@LINE-1]]:10 - [[@LINE-1]]:32]
// CHECK: index-concepts.cpp:[[@LINE-2]]:11: DeclRefExpr= Extent=[[[@LINE-2]]:11 - [[@LINE-2]]:31]
// CHECK: index-concepts.cpp:[[@LINE-3]]:11: TemplateRef=type_trait:4:8 Extent=[[[@LINE-3]]:11 - [[@LINE-3]]:21]
// CHECK: index-concepts.cpp:[[@LINE-4]]:22: TypeRef=T:22:16 Extent=[[[@LINE-4]]:22 - [[@LINE-4]]:23]
class IndexRequiresClauseInClass {};
template <class T>
concept Con1 = type_trait<T>::value;
// CHECK: index-concepts.cpp:[[@LINE-1]]:9: ConceptDecl=Con1:[[@LINE-1]]:9 (Definition) Extent=[[[@LINE-2]]:1 - [[@LINE-1]]:36]
// CHECK: index-concepts.cpp:[[@LINE-3]]:17: TemplateTypeParameter=T:[[@LINE-3]]:17 (Definition) Extent=[[[@LINE-3]]:11 - [[@LINE-3]]:18] [access=public]
// CHECK: index-concepts.cpp:[[@LINE-3]]:16: DeclRefExpr= Extent=[[[@LINE-3]]:16 - [[@LINE-3]]:36]
// CHECK: index-concepts.cpp:[[@LINE-4]]:16: TemplateRef=type_trait:4:8 Extent=[[[@LINE-4]]:16 - [[@LINE-4]]:26]
// CHECK: index-concepts.cpp:[[@LINE-5]]:27: TypeRef=T:30:17 Extent=[[[@LINE-5]]:27 - [[@LINE-5]]:28]
constexpr int sizeFunc() { return 4; }
template <class T>
concept ConWithLogicalAnd = Con1<T> && sizeof(T) > sizeFunc();
// CHECK: index-concepts.cpp:[[@LINE-1]]:9: ConceptDecl=ConWithLogicalAnd:[[@LINE-1]]:9 (Definition) Extent=[[[@LINE-2]]:1 - [[@LINE-1]]:62]
// CHECK: index-concepts.cpp:[[@LINE-3]]:17: TemplateTypeParameter=T:[[@LINE-3]]:17 (Definition) Extent=[[[@LINE-3]]:11 - [[@LINE-3]]:18] [access=public]
// CHECK: index-concepts.cpp:[[@LINE-3]]:29: BinaryOperator= Extent=[[[@LINE-3]]:29 - [[@LINE-3]]:62]
// CHECK: index-concepts.cpp:[[@LINE-4]]:29: ConceptSpecializationExpr= Extent=[[[@LINE-4]]:29 - [[@LINE-4]]:36]
// CHECK: index-concepts.cpp:[[@LINE-5]]:29: TemplateRef=Con1:31:9 Extent=[[[@LINE-5]]:29 - [[@LINE-5]]:33]
// CHECK: index-concepts.cpp:[[@LINE-6]]:40: BinaryOperator= Extent=[[[@LINE-6]]:40 - [[@LINE-6]]:62]
// CHECK: index-concepts.cpp:[[@LINE-7]]:40: UnaryExpr= Extent=[[[@LINE-7]]:40 - [[@LINE-7]]:49]
// CHECK: index-concepts.cpp:[[@LINE-8]]:47: TypeRef=T:40:17 Extent=[[[@LINE-8]]:47 - [[@LINE-8]]:48]
// CHECK: index-concepts.cpp:[[@LINE-9]]:52: UnexposedExpr=sizeFunc:38:15 Extent=[[[@LINE-9]]:52 - [[@LINE-9]]:62]
// CHECK: index-concepts.cpp:[[@LINE-10]]:52: CallExpr=sizeFunc:38:15 Extent=[[[@LINE-10]]:52 - [[@LINE-10]]:62]
// CHECK: index-concepts.cpp:[[@LINE-11]]:52: UnexposedExpr=sizeFunc:38:15 Extent=[[[@LINE-11]]:52 - [[@LINE-11]]:60]
// CHECK: index-concepts.cpp:[[@LINE-12]]:52: DeclRefExpr=sizeFunc:38:15 Extent=[[[@LINE-12]]:52 - [[@LINE-12]]:60]
namespace ns {
template <class T>
concept ConInNamespace = sizeof(T) > 4;
}
template <class T1, class T2>
concept ConTwoTemplateParams = ns::ConInNamespace<T1> && ConWithLogicalAnd<T2>;
// CHECK: index-concepts.cpp:[[@LINE-1]]:9: ConceptDecl=ConTwoTemplateParams:[[@LINE-1]]:9 (Definition) Extent=[[[@LINE-2]]:1 - [[@LINE-1]]:79]
// CHECK: index-concepts.cpp:[[@LINE-3]]:17: TemplateTypeParameter=T1:[[@LINE-3]]:17 (Definition) Extent=[[[@LINE-3]]:11 - [[@LINE-3]]:19] [access=public]
// CHECK: index-concepts.cpp:[[@LINE-4]]:27: TemplateTypeParameter=T2:[[@LINE-4]]:27 (Definition) Extent=[[[@LINE-4]]:21 - [[@LINE-4]]:29] [access=public]
// CHECK: index-concepts.cpp:[[@LINE-4]]:36: BinaryOperator= Extent=[[[@LINE-4]]:36 - [[@LINE-4]]:79]
// CHECK: index-concepts.cpp:[[@LINE-5]]:36: ConceptSpecializationExpr= Extent=[[[@LINE-5]]:36 - [[@LINE-5]]:54]
// CHECK: index-concepts.cpp:[[@LINE-6]]:32: NamespaceRef=ns:55:11 Extent=[[[@LINE-6]]:32 - [[@LINE-6]]:34]
// CHECK: index-concepts.cpp:[[@LINE-7]]:36: TemplateRef=ConInNamespace:58:9 Extent=[[[@LINE-7]]:36 - [[@LINE-7]]:50]
// CHECK: index-concepts.cpp:[[@LINE-8]]:58: ConceptSpecializationExpr= Extent=[[[@LINE-8]]:58 - [[@LINE-8]]:79]
// CHECK: index-concepts.cpp:[[@LINE-9]]:58: TemplateRef=ConWithLogicalAnd:41:9 Extent=[[[@LINE-9]]:58 - [[@LINE-9]]:75]
struct ConcreteType {};
template<class T>
requires ConTwoTemplateParams<T, ConcreteType>
struct UsesConceptInRequires {};
// CHECK: index-concepts.cpp:[[@LINE-1]]:8: ClassTemplate=UsesConceptInRequires:[[@LINE-1]]:8 (Definition) Extent=[[[@LINE-3]]:1 - [[@LINE-1]]:32]
// CHECK: index-concepts.cpp:[[@LINE-4]]:16: TemplateTypeParameter=T:[[@LINE-4]]:16 (Definition) Extent=[[[@LINE-4]]:10 - [[@LINE-4]]:17] [access=public]
// CHECK: index-concepts.cpp:[[@LINE-4]]:10: ConceptSpecializationExpr= Extent=[[[@LINE-4]]:10 - [[@LINE-4]]:47]
// CHECK: index-concepts.cpp:[[@LINE-5]]:10: TemplateRef=ConTwoTemplateParams:63:9 Extent=[[[@LINE-5]]:10 - [[@LINE-5]]:30]
// CHECK: index-concepts.cpp:[[@LINE-6]]:31: TypeRef=T:[[@LINE-7]]:16 Extent=[[[@LINE-6]]:31 - [[@LINE-6]]:32]
// CHECK: index-concepts.cpp:[[@LINE-7]]:34: TypeRef=struct ConcreteType:[[@LINE-10]]:8 Extent=[[[@LINE-7]]:34 - [[@LINE-7]]:46]
template<ConWithLogicalAnd T>
struct UsesConceptInTemplateArg {};
// CHECK: index-concepts.cpp:[[@LINE-1]]:8: ClassTemplate=UsesConceptInTemplateArg:[[@LINE-1]]:8 (Definition) Extent=[[[@LINE-2]]:1 - [[@LINE-1]]:35]
// CHECK: index-concepts.cpp:[[@LINE-3]]:28: TemplateTypeParameter=T:[[@LINE-3]]:28 (Definition) Extent=[[[@LINE-3]]:10 - [[@LINE-3]]:29] [access=public]
// CHECK: index-concepts.cpp:[[@LINE-4]]:10: TemplateRef=ConWithLogicalAnd:41:9 Extent=[[[@LINE-4]]:10 - [[@LINE-4]]:27]
void usesConceptInAutoParam(ns::ConInNamespace auto x) {}
// CHECK: index-concepts.cpp:[[@LINE-1]]:6: FunctionTemplate=usesConceptInAutoParam:[[@LINE-1]]:6 (Definition)
// CHECK: index-concepts.cpp:[[@LINE-2]]:53: ParmDecl=x:[[@LINE-2]]:53 (Definition) Extent=[[[@LINE-2]]:29 - [[@LINE-2]]:54]
// CHECK: index-concepts.cpp:[[@LINE-3]]:29: NamespaceRef=ns:55:11 Extent=[[[@LINE-3]]:29 - [[@LINE-3]]:31]
// CHECK: index-concepts.cpp:[[@LINE-4]]:33: TemplateRef=ConInNamespace:58:9 Extent=[[[@LINE-4]]:33 - [[@LINE-4]]:47]
// CHECK: index-concepts.cpp:[[@LINE-5]]:48: TypeRef=ns::ConInNamespace auto:[[@LINE-5]]:53 Extent=[[[@LINE-5]]:48 - [[@LINE-5]]:52]
// CHECK: index-concepts.cpp:[[@LINE-6]]:56: CompoundStmt= Extent=[[[@LINE-6]]:56 - [[@LINE-6]]:58]
template<class T>
void testTrailingRequires(const T &x)
requires ns::ConInNamespace<T> && ConTwoTemplateParams<T, ConcreteType> {}
// CHECK: index-concepts.cpp:[[@LINE-2]]:6: FunctionTemplate=testTrailingRequires:[[@LINE-2]]:6 (Definition) Extent=[[[@LINE-3]]:1 - [[@LINE-1]]:75]
// CHECK: index-concepts.cpp:[[@LINE-4]]:16: TemplateTypeParameter=T:[[@LINE-4]]:16 (Definition) Extent=[[[@LINE-4]]:10 - [[@LINE-4]]:17] [access=public]
// CHECK: index-concepts.cpp:[[@LINE-4]]:36: ParmDecl=x:[[@LINE-4]]:36 (Definition) Extent=[[[@LINE-4]]:27 - [[@LINE-4]]:37]
// CHECK: index-concepts.cpp:[[@LINE-5]]:33: TypeRef=T:[[@LINE-6]]:16 Extent=[[[@LINE-5]]:33 - [[@LINE-5]]:34]
// CHECK: index-concepts.cpp:[[@LINE-5]]:14: ConceptSpecializationExpr= Extent=[[[@LINE-5]]:14 - [[@LINE-5]]:31]
// CHECK: index-concepts.cpp:[[@LINE-6]]:10: NamespaceRef=ns:55:11 Extent=[[[@LINE-6]]:10 - [[@LINE-6]]:12]
// CHECK: index-concepts.cpp:[[@LINE-7]]:14: TemplateRef=ConInNamespace:58:9 Extent=[[[@LINE-7]]:14 - [[@LINE-7]]:28]
// CHECK: index-concepts.cpp:[[@LINE-8]]:29: TypeRef=T:[[@LINE-10]]:16 Extent=[[[@LINE-8]]:29 - [[@LINE-8]]:30]
// CHECK: index-concepts.cpp:[[@LINE-9]]:35: ConceptSpecializationExpr= Extent=[[[@LINE-9]]:35 - [[@LINE-9]]:72]
// CHECK: index-concepts.cpp:[[@LINE-10]]:35: TemplateRef=ConTwoTemplateParams:63:9 Extent=[[[@LINE-10]]:35 - [[@LINE-10]]:55]
// CHECK: index-concepts.cpp:[[@LINE-11]]:56: TypeRef=T:[[@LINE-13]]:16 Extent=[[[@LINE-11]]:56 - [[@LINE-11]]:57]
// CHECK: index-concepts.cpp:[[@LINE-12]]:59: TypeRef=struct ConcreteType:75:8 Extent=[[[@LINE-12]]:59 - [[@LINE-12]]:71]
void concreteFunc(ConcreteType);
template<class T>
void genericFunc(const T&x);
template<class T>
concept ConWithRequires = requires(const T& x, ConcreteType value) {
concreteFunc(value);
genericFunc(x);
};
// CHECK: index-concepts.cpp:[[@LINE-4]]:9: ConceptDecl=ConWithRequires:[[@LINE-4]]:9 (Definition) Extent=[[[@LINE-5]]:1 - [[@LINE-1]]:2]
// CHECK: index-concepts.cpp:[[@LINE-6]]:16: TemplateTypeParameter=T:[[@LINE-6]]:16 (Definition) Extent=[[[@LINE-6]]:10 - [[@LINE-6]]:17] [access=public]
// CHECK: index-concepts.cpp:[[@LINE-6]]:27: RequiresExpr= Extent=[[[@LINE-6]]:27 - [[@LINE-3]]:2]
// CHECK: index-concepts.cpp:[[@LINE-7]]:61: ParmDecl=value:[[@LINE-7]]:61 (Definition) Extent=[[[@LINE-7]]:48 - [[@LINE-7]]:66]
// CHECK: index-concepts.cpp:[[@LINE-8]]:48: TypeRef=struct ConcreteType:75:8 Extent=[[[@LINE-8]]:48 - [[@LINE-8]]:60]
// CHECK: index-concepts.cpp:[[@LINE-9]]:45: ParmDecl=x:[[@LINE-9]]:45 (Definition) Extent=[[[@LINE-9]]:36 - [[@LINE-9]]:46]
// CHECK: index-concepts.cpp:[[@LINE-10]]:42: TypeRef=T:[[@LINE-11]]:16 Extent=[[[@LINE-10]]:42 - [[@LINE-10]]:43]
// CHECK: index-concepts.cpp:[[@LINE-10]]:3: UnexposedExpr=concreteFunc:[[@LINE-17]]:6 Extent=[[[@LINE-10]]:3 - [[@LINE-10]]:15]
// CHECK: index-concepts.cpp:[[@LINE-11]]:3: DeclRefExpr=concreteFunc:[[@LINE-18]]:6 Extent=[[[@LINE-11]]:3 - [[@LINE-11]]:15]
// CHECK: index-concepts.cpp:[[@LINE-12]]:16: CallExpr=ConcreteType:75:8 Extent=[[[@LINE-12]]:16 - [[@LINE-12]]:21]
// CHECK: index-concepts.cpp:[[@LINE-13]]:16: UnexposedExpr=value:[[@LINE-14]]:61 Extent=[[[@LINE-13]]:16 - [[@LINE-13]]:21]
// CHECK: index-concepts.cpp:[[@LINE-14]]:16: DeclRefExpr=value:[[@LINE-15]]:61 Extent=[[[@LINE-14]]:16 - [[@LINE-14]]:21]
// CHECK: index-concepts.cpp:[[@LINE-14]]:3: DeclRefExpr=[[[@LINE-19]]:6] Extent=[[[@LINE-14]]:3 - [[@LINE-14]]:14]
// CHECK: index-concepts.cpp:[[@LINE-15]]:3: OverloadedDeclRef=genericFunc[[[@LINE-20]]:6] Extent=[[[@LINE-15]]:3 - [[@LINE-15]]:14]
// CHECK: index-concepts.cpp:[[@LINE-16]]:15: DeclRefExpr=x:[[@LINE-18]]:45 Extent=[[[@LINE-16]]:15 - [[@LINE-16]]:16]
template<class T>
concept ConWithCompRequires = requires {
{ genericFunc(T()) } -> ns::ConInNamespace;
{ genericFunc(T()) } -> ConTwoTemplateParams<ConcreteType>;
};
// CHECK: index-concepts.cpp:[[@LINE-4]]:9: ConceptDecl=ConWithCompRequires:[[@LINE-4]]:9 (Definition) Extent=[[[@LINE-5]]:1 - [[@LINE-1]]:2]
// CHECK: index-concepts.cpp:[[@LINE-6]]:16: TemplateTypeParameter=T:[[@LINE-6]]:16 (Definition) Extent=[[[@LINE-6]]:10 - [[@LINE-6]]:17] [access=public]
// CHECK: index-concepts.cpp:[[@LINE-6]]:31: RequiresExpr= Extent=[[[@LINE-6]]:31 - [[@LINE-3]]:2]
// CHECK: index-concepts.cpp:[[@LINE-6]]:5: DeclRefExpr=[123:6] Extent=[[[@LINE-6]]:5 - [[@LINE-6]]:16]
// CHECK: index-concepts.cpp:[[@LINE-7]]:5: OverloadedDeclRef=genericFunc[123:6] Extent=[[[@LINE-7]]:5 - [[@LINE-7]]:16]
// CHECK: index-concepts.cpp:[[@LINE-8]]:17: CallExpr= Extent=[[[@LINE-8]]:17 - [[@LINE-8]]:20]
// CHECK: index-concepts.cpp:[[@LINE-9]]:17: TypeRef=T:[[@LINE-11]]:16 Extent=[[[@LINE-9]]:17 - [[@LINE-9]]:18]
// CHECK: index-concepts.cpp:[[@LINE-10]]:27: NamespaceRef=ns:55:11 Extent=[[[@LINE-10]]:27 - [[@LINE-10]]:29]
// CHECK: index-concepts.cpp:[[@LINE-11]]:31: TemplateRef=ConInNamespace:58:9 Extent=[[[@LINE-11]]:31 - [[@LINE-11]]:45]
// CHECK: index-concepts.cpp:[[@LINE-11]]:5: DeclRefExpr=[123:6] Extent=[[[@LINE-11]]:5 - [[@LINE-11]]:16]
// CHECK: index-concepts.cpp:[[@LINE-12]]:5: OverloadedDeclRef=genericFunc[123:6] Extent=[[[@LINE-12]]:5 - [[@LINE-12]]:16]
// CHECK: index-concepts.cpp:[[@LINE-13]]:17: CallExpr= Extent=[[[@LINE-13]]:17 - [[@LINE-13]]:20]
// CHECK: index-concepts.cpp:[[@LINE-14]]:17: TypeRef=T:[[@LINE-17]]:16 Extent=[[[@LINE-14]]:17 - [[@LINE-14]]:18]
// CHECK: index-concepts.cpp:[[@LINE-15]]:27: TemplateRef=ConTwoTemplateParams:63:9 Extent=[[[@LINE-15]]:27 - [[@LINE-15]]:47]
// CHECK: index-concepts.cpp:[[@LINE-16]]:48: TypeRef=struct ConcreteType:75:8 Extent=[[[@LINE-16]]:48 - [[@LINE-16]]:60]
template<class T>
concept ConWithTypeReq = requires {
typename type_trait<T>;
};
// CHECK: index-concepts.cpp:[[@LINE-3]]:9: ConceptDecl=ConWithTypeReq:[[@LINE-3]]:9 (Definition) Extent=[[[@LINE-4]]:1 - [[@LINE-1]]:2]
// CHECK: index-concepts.cpp:[[@LINE-5]]:16: TemplateTypeParameter=T:[[@LINE-5]]:16 (Definition) Extent=[[[@LINE-5]]:10 - [[@LINE-5]]:17] [access=public]
// CHECK: index-concepts.cpp:[[@LINE-5]]:26: RequiresExpr= Extent=[[[@LINE-5]]:26 - [[@LINE-3]]:2]
// CHECK: index-concepts.cpp:[[@LINE-5]]:12: TemplateRef=type_trait:4:8 Extent=[[[@LINE-5]]:12 - [[@LINE-5]]:22]
// CHECK: index-concepts.cpp:[[@LINE-6]]:23: TypeRef=T:[[@LINE-8]]:16 Extent=[[[@LINE-6]]:23 - [[@LINE-6]]:24]
template<class T>
concept ConWithNestedReq = requires {
requires ns::ConInNamespace<T>;
};
// CHECK: index-concepts.cpp:[[@LINE-3]]:9: ConceptDecl=ConWithNestedReq:[[@LINE-3]]:9 (Definition) Extent=[[[@LINE-4]]:1 - [[@LINE-1]]:2]
// CHECK: index-concepts.cpp:[[@LINE-5]]:16: TemplateTypeParameter=T:[[@LINE-5]]:16 (Definition) Extent=[[[@LINE-5]]:10 - [[@LINE-5]]:17] [access=public]
// CHECK: index-concepts.cpp:[[@LINE-5]]:28: RequiresExpr= Extent=[[[@LINE-5]]:28 - [[@LINE-3]]:2]
// CHECK: index-concepts.cpp:[[@LINE-5]]:12: NamespaceRef=ns:55:11 Extent=[[[@LINE-5]]:12 - [[@LINE-5]]:14]
// CHECK: index-concepts.cpp:[[@LINE-6]]:16: TemplateRef=ConInNamespace:58:9 Extent=[[[@LINE-6]]:16 - [[@LINE-6]]:30]
// CHECK: index-concepts.cpp:[[@LINE-7]]:31: TypeRef=T:[[@LINE-9]]:16 Extent=[[[@LINE-7]]:31 - [[@LINE-7]]:32]

View File

@@ -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;

View File

@@ -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");

View File

@@ -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;

View File

@@ -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");
}

View File

@@ -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,

View File

@@ -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);