diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2189,7 +2189,17 @@ */ 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 @@ * 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 @@ CXIdxEntity_CXXDestructor = 23, CXIdxEntity_CXXConversionFunction = 24, CXIdxEntity_CXXTypeAlias = 25, - CXIdxEntity_CXXInterface = 26 + CXIdxEntity_CXXInterface = 26, + CXIdxEntity_CXXConcept = 27 } CXIdxEntityKind; diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -4044,6 +4044,9 @@ case Decl::ObjCTypeParam: return CXCursor_TemplateTypeParameter; + case Decl::Concept: + return CXCursor_ConceptDecl; + default: if (const auto *TD = dyn_cast(D)) { switch (TD->getTagKind()) { diff --git a/clang/test/Index/index-concept-kind.cpp b/clang/test/Index/index-concept-kind.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Index/index-concept-kind.cpp @@ -0,0 +1,9 @@ +// RUN: c-index-test -index-file %s -std=gnu++20 | FileCheck %s + +template +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 +// CHECK: [indexEntityReference]: kind: concept | name: LargeType | USR: c:@CT@LargeType | lang: C | cursor: TemplateRef=LargeType:4:9 | loc: [[@LINE-1]]:11 | :: kind: function-template | name: f | USR: c:@FT@>1#Tf#v# | lang: C++ | container: [<>] | refkind: direct | role: ref +void f(); diff --git a/clang/test/Index/index-concepts.cpp b/clang/test/Index/index-concepts.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Index/index-concepts.cpp @@ -0,0 +1,186 @@ +// RUN: c-index-test -test-load-source all %s -std=gnu++20 -fno-delayed-template-parsing | FileCheck %s + +template +struct type_trait { + const static bool value = false; +}; + +template<> +struct type_trait { + const static bool value = true; +}; + +template +requires (type_trait::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 +requires (type_trait::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 +concept Con1 = type_trait::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 +concept ConWithLogicalAnd = Con1 && 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 +concept ConInNamespace = sizeof(T) > 4; + +} + +template +concept ConTwoTemplateParams = ns::ConInNamespace && ConWithLogicalAnd; +// 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 +requires ConTwoTemplateParams +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 +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 +void testTrailingRequires(const T &x) +requires ns::ConInNamespace && ConTwoTemplateParams {} +// 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 +void genericFunc(const T&x); + +template +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 +concept ConWithCompRequires = requires { + { genericFunc(T()) } -> ns::ConInNamespace; + { genericFunc(T()) } -> ConTwoTemplateParams; +}; +// 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 +concept ConWithTypeReq = requires { + typename type_trait; +}; +// 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 +concept ConWithNestedReq = requires { + requires ns::ConInNamespace; +}; +// 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] diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c --- a/clang/tools/c-index-test/c-index-test.c +++ b/clang/tools/c-index-test/c-index-test.c @@ -3504,6 +3504,8 @@ 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 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -761,10 +761,10 @@ } 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 @@ // FIXME: Attributes? } + if (auto *E = ND->getTrailingRequiresClause()) { + if (Visit(E)) + return true; + } + if (ND->doesThisDeclarationHaveABody() && !ND->isLateTemplateParsed()) { if (CXXConstructorDecl *Constructor = dyn_cast(ND)) { // Find the initializers that were written in the source. @@ -1310,6 +1315,75 @@ 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(R); + if (!TR.isSubstitutionFailure()) { + if (Visit(TR.getType()->getTypeLoc())) + return true; + } + break; + } + case Requirement::RK_Simple: + case Requirement::RK_Compound: { + const ExprRequirement &ER = cast(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(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 @@ 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::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(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 @@ 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 @@ 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 @@ break; } + case VisitorJob::ConceptSpecializationExprVisitKind: { + const ConceptSpecializationExpr *E = + cast(&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(&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 @@ 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 @@ 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 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -299,8 +299,6 @@ 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 @@ 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.h b/clang/tools/libclang/CXIndexDataConsumer.h --- a/clang/tools/libclang/CXIndexDataConsumer.h +++ b/clang/tools/libclang/CXIndexDataConsumer.h @@ -409,6 +409,8 @@ 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/CXIndexDataConsumer.cpp b/clang/tools/libclang/CXIndexDataConsumer.cpp --- a/clang/tools/libclang/CXIndexDataConsumer.cpp +++ b/clang/tools/libclang/CXIndexDataConsumer.cpp @@ -146,6 +146,11 @@ DataConsumer.importedModule(D); return true; } + + bool VisitConceptDecl(const ConceptDecl *D) { + DataConsumer.handleConcept(D); + return true; + } }; CXSymbolRole getSymbolRole(SymbolRoleSet Role) { @@ -883,6 +888,12 @@ 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 @@ 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 @@ 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/CursorVisitor.h b/clang/tools/libclang/CursorVisitor.h --- a/clang/tools/libclang/CursorVisitor.h +++ b/clang/tools/libclang/CursorVisitor.h @@ -19,6 +19,10 @@ class PreprocessingRecord; class ASTUnit; +namespace concepts { +class Requirement; +} + namespace cxcursor { class VisitorJob { @@ -37,6 +41,8 @@ MemberRefVisitKind, SizeOfPackExprPartsKind, LambdaExprPartsKind, + ConceptSpecializationExprVisitKind, + RequiresExprVisitKind, PostChildrenVisitKind }; @@ -242,6 +248,9 @@ 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);