Skip to content

Commit 2974a4e

Browse files
author
git apple-llvm automerger
committed
Merge commit 'ca7e45531df3' from swift/release/5.7 into stable/20211026
2 parents 5a0a698 + ca7e455 commit 2974a4e

28 files changed

+575
-41
lines changed

clang-tools-extra/clangd/CodeComplete.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ CompletionItemKind toCompletionItemKind(index::SymbolKind Kind) {
131131
case SK::TemplateTypeParm:
132132
case SK::TemplateTemplateParm:
133133
return CompletionItemKind::TypeParameter;
134+
case SK::Concept:
135+
return CompletionItemKind::Interface;
134136
}
135137
llvm_unreachable("Unhandled clang::index::SymbolKind.");
136138
}

clang-tools-extra/clangd/Protocol.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,8 @@ SymbolKind indexSymbolKindToSymbolKind(index::SymbolKind Kind) {
305305
case index::SymbolKind::TemplateTemplateParm:
306306
case index::SymbolKind::TemplateTypeParm:
307307
return SymbolKind::TypeParameter;
308+
case index::SymbolKind::Concept:
309+
return SymbolKind::Interface;
308310
}
309311
llvm_unreachable("invalid symbol kind");
310312
}

clang-tools-extra/clangd/Quality.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ categorize(const index::SymbolInfo &D) {
132132
case index::SymbolKind::TypeAlias:
133133
case index::SymbolKind::TemplateTypeParm:
134134
case index::SymbolKind::TemplateTemplateParm:
135+
case index::SymbolKind::Concept:
135136
return SymbolQualitySignals::Type;
136137
case index::SymbolKind::Function:
137138
case index::SymbolKind::ClassMethod:

clang-tools-extra/clangd/index/SymbolCollector.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ bool shouldCollectIncludePath(index::SymbolKind Kind) {
9191
case SK::Function:
9292
case SK::Variable:
9393
case SK::EnumConstant:
94+
case SK::Concept:
9495
return true;
9596
default:
9697
return false;

clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3308,6 +3308,38 @@ TEST(CompletionTest, CommentParamName) {
33083308
IsEmpty());
33093309
}
33103310

3311+
TEST(CompletionTest, Concepts) {
3312+
Annotations Code(R"cpp(
3313+
template<class T>
3314+
concept A = sizeof(T) <= 8;
3315+
3316+
template<$tparam^A U>
3317+
int foo();
3318+
3319+
template<class T>
3320+
concept b = $other^A<T> && $other^sizeof(T) % 2 == 0 || $other^A<T> && sizeof(T) == 1;
3321+
3322+
$other^A<T> auto i = 19;
3323+
)cpp");
3324+
TestTU TU;
3325+
TU.Code = Code.code().str();
3326+
TU.ExtraArgs = {"-std=c++20"};
3327+
3328+
std::vector<Symbol> Syms = {conceptSym("same_as")};
3329+
for (auto P : Code.points("tparam")) {
3330+
ASSERT_THAT(completions(TU, P, Syms).Completions,
3331+
AllOf(Contains(named("A")), Contains(named("same_as")),
3332+
Contains(named("class")), Contains(named("typename"))))
3333+
<< "Completing template parameter at position " << P;
3334+
}
3335+
3336+
for (auto P : Code.points("other")) {
3337+
EXPECT_THAT(completions(TU, P, Syms).Completions,
3338+
AllOf(Contains(named("A")), Contains(named("same_as"))))
3339+
<< "Completing 'requires' expression at position " << P;
3340+
}
3341+
}
3342+
33113343
} // namespace
33123344
} // namespace clangd
33133345
} // namespace clang

clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ MATCHER_P(HasName, Name, "") { return arg.Name == Name; }
5959
MATCHER_P(TemplateArgs, TemplArgs, "") {
6060
return arg.TemplateSpecializationArgs == TemplArgs;
6161
}
62+
MATCHER_P(hasKind, Kind, "") { return arg.SymInfo.Kind == Kind; }
6263
MATCHER_P(DeclURI, P, "") {
6364
return StringRef(arg.CanonicalDeclaration.FileURI) == P;
6465
}
@@ -1849,6 +1850,17 @@ TEST_F(SymbolCollectorTest, NoCrashOnObjCMethodCStyleParam) {
18491850
UnorderedElementsAre(QName("Foo"), QName("Foo::fun:")));
18501851
}
18511852

1853+
TEST_F(SymbolCollectorTest, Concepts) {
1854+
const char *Header = R"cpp(
1855+
template <class T>
1856+
concept A = sizeof(T) <= 8;
1857+
)cpp";
1858+
runSymbolCollector("", Header, {"-std=c++20"});
1859+
EXPECT_THAT(Symbols,
1860+
UnorderedElementsAre(AllOf(
1861+
qName("A"), hasKind(clang::index::SymbolKind::Concept))));
1862+
}
1863+
18521864
} // namespace
18531865
} // namespace clangd
18541866
} // namespace clang

clang-tools-extra/clangd/unittests/TestIndex.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ Symbol ns(llvm::StringRef Name) {
7373
return sym(Name, index::SymbolKind::Namespace, "@N@\\0");
7474
}
7575

76+
Symbol conceptSym(llvm::StringRef Name) {
77+
return sym(Name, index::SymbolKind::Concept, "@CT@\\0");
78+
}
79+
7680
SymbolSlab generateSymbols(std::vector<std::string> QualifiedNames) {
7781
SymbolSlab::Builder Slab;
7882
for (llvm::StringRef QName : QualifiedNames)

clang-tools-extra/clangd/unittests/TestIndex.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ Symbol cls(llvm::StringRef Name);
3030
Symbol var(llvm::StringRef Name);
3131
// Creates a namespace symbol.
3232
Symbol ns(llvm::StringRef Name);
33+
// Create a C++20 concept symbol.
34+
Symbol conceptSym(llvm::StringRef Name);
3335

3436
// Create a slab of symbols with the given qualified names as IDs and names.
3537
SymbolSlab generateSymbols(std::vector<std::string> QualifiedNames);

clang-tools-extra/clangd/unittests/XRefsTests.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,6 +1771,8 @@ TEST(FindImplementations, CaptureDefintion) {
17711771
void checkFindRefs(llvm::StringRef Test, bool UseIndex = false) {
17721772
Annotations T(Test);
17731773
auto TU = TestTU::withCode(T.code());
1774+
TU.ExtraArgs.push_back("-std=c++20");
1775+
17741776
auto AST = TU.build();
17751777
std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
17761778
for (const auto &R : T.ranges())
@@ -1985,6 +1987,38 @@ TEST(FindReferences, WithinAST) {
19851987
checkFindRefs(Test);
19861988
}
19871989

1990+
TEST(FindReferences, ConceptsWithinAST) {
1991+
constexpr llvm::StringLiteral Code = R"cpp(
1992+
template <class T>
1993+
concept $def[[IsSmal^l]] = sizeof(T) <= 8;
1994+
1995+
template <class T>
1996+
concept IsSmallPtr = requires(T x) {
1997+
{ *x } -> [[IsSmal^l]];
1998+
};
1999+
2000+
[[IsSmall]] auto i = 'c';
2001+
template<[[IsSmal^l]] U> void foo();
2002+
template<class U> void bar() requires [[IsSmal^l]]<U>;
2003+
template<class U> requires [[IsSmal^l]]<U> void baz();
2004+
static_assert([[IsSma^ll]]<char>);
2005+
)cpp";
2006+
checkFindRefs(Code);
2007+
}
2008+
2009+
TEST(FindReferences, RequiresExprParameters) {
2010+
constexpr llvm::StringLiteral Code = R"cpp(
2011+
template <class T>
2012+
concept IsSmall = sizeof(T) <= 8;
2013+
2014+
template <class T>
2015+
concept IsSmallPtr = requires(T $def[[^x]]) {
2016+
{ *[[^x]] } -> IsSmall;
2017+
};
2018+
)cpp";
2019+
checkFindRefs(Code);
2020+
}
2021+
19882022
TEST(FindReferences, IncludeOverrides) {
19892023
llvm::StringRef Test =
19902024
R"cpp(

clang/include/clang-c/Index.h

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2189,7 +2189,17 @@ enum CXCursorKind {
21892189
*/
21902190
CXCursor_CXXAddrspaceCastExpr = 152,
21912191

2192-
CXCursor_LastExpr = CXCursor_CXXAddrspaceCastExpr,
2192+
/**
2193+
* Expression that references a C++20 concept.
2194+
*/
2195+
CXCursor_ConceptSpecializationExpr = 153,
2196+
2197+
/**
2198+
* Expression that references a C++20 concept.
2199+
*/
2200+
CXCursor_RequiresExpr = 154,
2201+
2202+
CXCursor_LastExpr = CXCursor_RequiresExpr,
21932203

21942204
/* Statements */
21952205
CXCursor_FirstStmt = 200,
@@ -2680,8 +2690,13 @@ enum CXCursorKind {
26802690
* a friend declaration.
26812691
*/
26822692
CXCursor_FriendDecl = 603,
2693+
/**
2694+
* a concept declaration.
2695+
*/
2696+
CXCursor_ConceptDecl = 604,
2697+
26832698
CXCursor_FirstExtraDecl = CXCursor_ModuleImportDecl,
2684-
CXCursor_LastExtraDecl = CXCursor_FriendDecl,
2699+
CXCursor_LastExtraDecl = CXCursor_ConceptDecl,
26852700

26862701
/**
26872702
* A code completion overload candidate.
@@ -6297,7 +6312,8 @@ typedef enum {
62976312
CXIdxEntity_CXXDestructor = 23,
62986313
CXIdxEntity_CXXConversionFunction = 24,
62996314
CXIdxEntity_CXXTypeAlias = 25,
6300-
CXIdxEntity_CXXInterface = 26
6315+
CXIdxEntity_CXXInterface = 26,
6316+
CXIdxEntity_CXXConcept = 27
63016317

63026318
} CXIdxEntityKind;
63036319

clang/include/clang/AST/ExprConcepts.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ class ConceptSpecializationExpr final : public Expr, public ConceptReference,
122122
}
123123

124124
SourceLocation getBeginLoc() const LLVM_READONLY {
125+
if (auto QualifierLoc = getNestedNameSpecifierLoc())
126+
return QualifierLoc.getBeginLoc();
125127
return ConceptName.getBeginLoc();
126128
}
127129

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2795,9 +2795,10 @@ DEF_TRAVERSE_STMT(RequiresExpr, {
27952795
if (!ExprReq->isExprSubstitutionFailure())
27962796
TRY_TO(TraverseStmt(ExprReq->getExpr()));
27972797
auto &RetReq = ExprReq->getReturnTypeRequirement();
2798-
if (RetReq.isTypeConstraint())
2799-
TRY_TO(TraverseTemplateParameterListHelper(
2800-
RetReq.getTypeConstraintTemplateParameterList()));
2798+
if (RetReq.isTypeConstraint()) {
2799+
TRY_TO(TraverseStmt(
2800+
RetReq.getTypeConstraint()->getImmediatelyDeclaredConstraint()));
2801+
}
28012802
} else {
28022803
auto *NestedReq = cast<concepts::NestedRequirement>(Req);
28032804
if (!NestedReq->isSubstitutionFailure())

clang/include/clang/Index/IndexSymbol.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ enum class SymbolKind : uint8_t {
5959
TemplateTypeParm,
6060
TemplateTemplateParm,
6161
NonTypeTemplateParm,
62+
63+
Concept, /// C++20 concept.
6264
};
6365

6466
enum class SymbolLanguage : uint8_t {

clang/lib/Index/IndexBody.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "IndexingContext.h"
10-
#include "clang/AST/RecursiveASTVisitor.h"
10+
#include "clang/AST/ASTConcept.h"
1111
#include "clang/AST/ASTLambda.h"
12+
#include "clang/AST/DeclCXX.h"
13+
#include "clang/AST/ExprConcepts.h"
14+
#include "clang/AST/RecursiveASTVisitor.h"
15+
#include "clang/AST/Type.h"
1216

1317
using namespace clang;
1418
using namespace clang::index;
@@ -455,10 +459,10 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
455459
}
456460

457461
bool VisitParmVarDecl(ParmVarDecl* D) {
458-
// Index the parameters of lambda expression.
462+
// Index the parameters of lambda expression and requires expression.
459463
if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
460464
const auto *DC = D->getDeclContext();
461-
if (DC && isLambdaCallOperator(DC))
465+
if (DC && (isLambdaCallOperator(DC) || isa<RequiresExprBodyDecl>(DC)))
462466
IndexCtx.handleDecl(D);
463467
}
464468
return true;
@@ -472,6 +476,21 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
472476
Relations, E);
473477
return true;
474478
}
479+
480+
bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *R) {
481+
IndexCtx.handleReference(R->getNamedConcept(), R->getConceptNameLoc(),
482+
Parent, ParentDC);
483+
return true;
484+
}
485+
486+
bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
487+
// This handles references in return type requirements of RequiresExpr.
488+
// E.g. `requires (T x) { {*x} -> ConceptRef }`
489+
if (auto *C = D->getTypeConstraint())
490+
IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(),
491+
Parent, ParentDC);
492+
return true;
493+
}
475494
};
476495

477496
} // anonymous namespace

clang/lib/Index/IndexDecl.cpp

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "IndexingContext.h"
10+
#include "clang/AST/ASTConcept.h"
1011
#include "clang/AST/Attr.h"
1112
#include "clang/AST/Decl.h"
13+
#include "clang/AST/DeclTemplate.h"
1214
#include "clang/AST/DeclVisitor.h"
1315
#include "clang/Index/IndexDataConsumer.h"
16+
#include "clang/Index/IndexSymbol.h"
1417

1518
using namespace clang;
1619
using namespace index;
@@ -129,6 +132,8 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
129132
}
130133
}
131134
}
135+
if (auto *C = D->getTrailingRequiresClause())
136+
IndexCtx.indexBody(C, Parent);
132137
}
133138

134139
bool handleObjCMethod(const ObjCMethodDecl *D,
@@ -688,36 +693,52 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
688693
return true;
689694
}
690695

691-
bool VisitTemplateDecl(const TemplateDecl *D) {
696+
void indexTemplateParameters(TemplateParameterList *Params,
697+
const NamedDecl *Parent) {
698+
for (const NamedDecl *TP : *Params) {
699+
if (IndexCtx.shouldIndexTemplateParameters())
700+
IndexCtx.handleDecl(TP);
701+
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) {
702+
if (TTP->hasDefaultArgument())
703+
IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent);
704+
if (auto *C = TTP->getTypeConstraint())
705+
IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(),
706+
Parent, TTP->getLexicalDeclContext());
707+
} else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) {
708+
if (NTTP->hasDefaultArgument())
709+
IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent);
710+
} else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) {
711+
if (TTPD->hasDefaultArgument())
712+
handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,
713+
TP->getLexicalDeclContext());
714+
}
715+
}
716+
if (auto *R = Params->getRequiresClause())
717+
IndexCtx.indexBody(R, Parent);
718+
}
692719

720+
bool VisitTemplateDecl(const TemplateDecl *D) {
693721
const NamedDecl *Parent = D->getTemplatedDecl();
694722
if (!Parent)
695723
return true;
696724

697725
// Index the default values for the template parameters.
698-
if (D->getTemplateParameters() &&
699-
shouldIndexTemplateParameterDefaultValue(Parent)) {
700-
const TemplateParameterList *Params = D->getTemplateParameters();
701-
for (const NamedDecl *TP : *Params) {
702-
if (IndexCtx.shouldIndexTemplateParameters())
703-
IndexCtx.handleDecl(TP);
704-
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) {
705-
if (TTP->hasDefaultArgument())
706-
IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent);
707-
} else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) {
708-
if (NTTP->hasDefaultArgument())
709-
IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent);
710-
} else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) {
711-
if (TTPD->hasDefaultArgument())
712-
handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,
713-
TP->getLexicalDeclContext());
714-
}
715-
}
726+
auto *Params = D->getTemplateParameters();
727+
if (Params && shouldIndexTemplateParameterDefaultValue(Parent)) {
728+
indexTemplateParameters(Params, Parent);
716729
}
717730

718731
return Visit(Parent);
719732
}
720733

734+
bool VisitConceptDecl(const ConceptDecl *D) {
735+
if (auto *Params = D->getTemplateParameters())
736+
indexTemplateParameters(Params, D);
737+
if (auto *E = D->getConstraintExpr())
738+
IndexCtx.indexBody(E, D);
739+
return IndexCtx.handleDecl(D);
740+
}
741+
721742
bool VisitFriendDecl(const FriendDecl *D) {
722743
if (auto ND = D->getFriendDecl()) {
723744
// FIXME: Ignore a class template in a dependent context, these are not

0 commit comments

Comments
 (0)