[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:
@@ -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;
|
||||
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
9
clang/test/Index/index-concept-kind.cpp
Normal file
9
clang/test/Index/index-concept-kind.cpp
Normal 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();
|
||||
186
clang/test/Index/index-concepts.cpp
Normal file
186
clang/test/Index/index-concepts.cpp
Normal 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]
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user