[PATCH] D73596: [CodeComplete] WIP member completion for concept-constrained type parameters

2020-01-28 Thread pre-merge checks [bot] via Phabricator via cfe-commits
merge_guards_bot added a comment.

{icon check-circle color=green} Unit tests: pass. 62281 tests passed, 0 failed 
and 827 were skipped.

{icon times-circle color=red} clang-tidy: fail. clang-tidy found 0 errors and 7 
warnings 
.
 0 of them are added as review comments below (why? 
).

{icon check-circle color=green} clang-format: pass.

Build artifacts 
: 
diff.json 
,
 clang-tidy.txt 
,
 clang-format.patch 
,
 CMakeCache.txt 
,
 console-log.txt 
,
 test-results.xml 


//Pre-merge checks is in beta. Report issue 
.
 Please join beta  or enable 
it for your project 
.//


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73596/new/

https://reviews.llvm.org/D73596



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D73596: [CodeComplete] WIP member completion for concept-constrained type parameters

2020-01-28 Thread Sam McCall via Phabricator via cfe-commits
sammccall created this revision.
Herald added subscribers: cfe-commits, usaxena95, kadircet, mgrang, 
ilya-biryukov.
Herald added a project: clang.

see https://github.com/clangd/clangd/issues/261


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D73596

Files:
  clang/include/clang/Sema/Scope.h
  clang/lib/Sema/SemaCodeComplete.cpp

Index: clang/lib/Sema/SemaCodeComplete.cpp
===
--- clang/lib/Sema/SemaCodeComplete.cpp
+++ clang/lib/Sema/SemaCodeComplete.cpp
@@ -16,8 +16,11 @@
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprConcepts.h"
 #include "clang/AST/ExprObjC.h"
+#include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/QualTypeNames.h"
+#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/CharInfo.h"
 #include "clang/Basic/Specifiers.h"
@@ -4746,6 +4749,281 @@
   return nullptr;
 }
 
+namespace {
+
+// Returns the DeclContext immediately enclosed by the template parameter scope.
+// For primary templates, this is the templated (e.g.) CXXRecordDecl.
+// For specializations, this is e.g. ClassTemplatPartialSpecializationDecl.
+DeclContext *getTemplatedEntity(const TemplateTypeParmDecl *D, Scope *S) {
+  if (D == nullptr)
+return nullptr;
+  Scope *Inner = nullptr;
+  while (S) {
+if (S->isTemplateParamScope() && S->isDeclScope(D))
+  return Inner->getEntity();
+Inner = S;
+S = S->getParent();
+  }
+  return nullptr;
+}
+
+llvm::SmallVector
+constraintsForTemplatedEntity(DeclContext *E) {
+  llvm::SmallVector Result;
+  if (E == nullptr)
+return Result;
+  llvm::cast(E)->dump();
+  // Primary templates can have constraints.
+  if (const auto *TD = llvm::cast(E)->getDescribedTemplate())
+TD->getAssociatedConstraints(Result);
+  // Partial specializations may have constraints.
+  if (const auto *CTPSD =
+  llvm::dyn_cast(E))
+CTPSD->getAssociatedConstraints(Result);
+  if (const auto *VTPSD =
+  llvm::dyn_cast(E))
+VTPSD->getAssociatedConstraints(Result);
+  return Result;
+}
+
+// Describes a likely member of a type, inferred by concept constraints.
+// Offered as a code completion for T. T-> and T:: contexts.
+struct ConceptMemberResult {
+  const IdentifierInfo *Name = nullptr;
+  llvm::Optional> ArgTypes; // For functions.
+  enum ResultKind {
+Function,
+Variable,
+Type,
+  } Kind = Variable;
+  enum AccessType {
+Dot,
+Arrow,
+Colons,
+  } Operator = Dot;
+
+  // For now we simply return these results as "pattern" strings.
+  CodeCompletionString *render(Sema , CodeCompletionAllocator ,
+   CodeCompletionTUInfo ) const {
+CodeCompletionBuilder B(Alloc, Info);
+B.AddTypedTextChunk(Alloc.CopyString(Name->getName()));
+if (ArgTypes) {
+  B.AddChunk(clang::CodeCompletionString::CK_LeftParen);
+  bool First = true;
+  for (QualType Arg : *ArgTypes) {
+if (First)
+  First = false;
+else {
+  B.AddChunk(clang::CodeCompletionString::CK_Comma);
+  B.AddChunk(clang::CodeCompletionString::CK_HorizontalSpace);
+}
+B.AddPlaceholderChunk(
+Alloc.CopyString(Arg.getAsString(getCompletionPrintingPolicy(S;
+  }
+  B.AddChunk(clang::CodeCompletionString::CK_RightParen);
+}
+return B.TakeString();
+  }
+};
+
+// Attempts to determine likely members of a concept-constrained type T
+// by examining the constraint expressions.
+//
+// For example, given:
+//   template  concept X = requires (T t) { t.foo(); };
+//   template  void foo(U u) { u.^ }
+// We should offer the completion 'foo()':
+// - u has type U
+// - so X holds
+// - X requires t.foo() to be valid, where t has type T.
+//
+// The design is very simple: we walk down each constraint looking for
+// expressions of the form T.foo().
+// If we're extra lucky, the return type is specified.
+// We don't do any clever handling of && or || in constraint expressions.
+//
+// FIXME: it some of this machinery could be used for non-concept tparms too,
+// enabling completion for type parameters based on other uses of that param.
+class ConceptMembers {
+  llvm::DenseMap Results;
+
+public:
+  ConceptMembers(const TemplateTypeParmType , Scope *S) {
+auto *TemplatedEntity = getTemplatedEntity(BaseType.getDecl(), S);
+for (const Expr *E : constraintsForTemplatedEntity(TemplatedEntity))
+  believe(E, );
+  }
+
+  std::vector results() {
+std::vector Results;
+for (const auto  : this->Results)
+  Results.push_back(E.second);
+llvm::sort(Results,
+   [](const ConceptMemberResult , const ConceptMemberResult ) {
+ return L.Name->getName() < R.Name->getName();
+   });
+return Results;
+  }
+
+  // Infer members of T, given that the expression E (dependent on T) is true.
+  void believe(const