summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clangd/ExpectedTypes.cpp
diff options
context:
space:
mode:
authorIlya Biryukov <ibiryukov@google.com>2018-11-26 15:25:20 +0000
committerIlya Biryukov <ibiryukov@google.com>2018-11-26 15:25:20 +0000
commitd360b2984e854bf7414239f66e81427cf0e25f1e (patch)
tree70ce372a5cd1208b83ccaf74a2ddac197628a758 /clang-tools-extra/clangd/ExpectedTypes.cpp
parenta622484fa64e03a45832a95cda1ba61d512244a0 (diff)
downloadbcm5719-llvm-d360b2984e854bf7414239f66e81427cf0e25f1e.tar.gz
bcm5719-llvm-d360b2984e854bf7414239f66e81427cf0e25f1e.zip
[clangd] Initial implementation of expected types
Summary: Provides facilities to model the C++ conversion rules without the AST. The introduced representation can be stored in the index and used to implement type-based ranking improvements for index-based completions. Reviewers: sammccall, ioeric Reviewed By: sammccall Subscribers: malaperle, mgorny, MaskRay, jkorous, arphaman, kadircet, cfe-commits Differential Revision: https://reviews.llvm.org/D52273 llvm-svn: 347559
Diffstat (limited to 'clang-tools-extra/clangd/ExpectedTypes.cpp')
-rw-r--r--clang-tools-extra/clangd/ExpectedTypes.cpp80
1 files changed, 80 insertions, 0 deletions
diff --git a/clang-tools-extra/clangd/ExpectedTypes.cpp b/clang-tools-extra/clangd/ExpectedTypes.cpp
new file mode 100644
index 00000000000..5c9cec89c26
--- /dev/null
+++ b/clang-tools-extra/clangd/ExpectedTypes.cpp
@@ -0,0 +1,80 @@
+#include "ExpectedTypes.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+#include "clang/Index/USRGeneration.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "llvm/ADT/STLExtras.h"
+
+using namespace llvm;
+
+namespace clang {
+namespace clangd {
+namespace {
+
+static const Type *toEquivClass(ASTContext &Ctx, QualType T) {
+ if (T.isNull() || T->isDependentType())
+ return nullptr;
+ // Drop references, we do not handle reference inits properly anyway.
+ T = T.getCanonicalType().getNonReferenceType();
+ // Numeric types are the simplest case.
+ if (T->isBooleanType())
+ return Ctx.BoolTy.getTypePtr();
+ if (T->isIntegerType() && !T->isEnumeralType())
+ return Ctx.IntTy.getTypePtr(); // All integers are equivalent.
+ if (T->isFloatingType() && !T->isComplexType())
+ return Ctx.FloatTy.getTypePtr(); // All floats are equivalent.
+
+ // Do some simple transformations.
+ if (T->isArrayType()) // Decay arrays to pointers.
+ return Ctx.getPointerType(QualType(T->getArrayElementTypeNoTypeQual(), 0))
+ .getTypePtr();
+ // Drop the qualifiers and return the resulting type.
+ // FIXME: also drop qualifiers from pointer types, e.g. 'const T* => T*'
+ return T.getTypePtr();
+}
+
+static Optional<QualType> typeOfCompletion(const CodeCompletionResult &R) {
+ auto *VD = dyn_cast_or_null<ValueDecl>(R.Declaration);
+ if (!VD)
+ return None; // We handle only variables and functions below.
+ auto T = VD->getType();
+ if (auto FuncT = T->getAs<FunctionType>()) {
+ // Functions are a special case. They are completed as 'foo()' and we want
+ // to match their return type rather than the function type itself.
+ // FIXME(ibiryukov): in some cases, we might want to avoid completing `()`
+ // after the function name, e.g. `std::cout << std::endl`.
+ return FuncT->getReturnType();
+ }
+ return T;
+}
+} // namespace
+
+Optional<OpaqueType> OpaqueType::encode(ASTContext &Ctx, QualType T) {
+ if (T.isNull())
+ return None;
+ const Type *C = toEquivClass(Ctx, T);
+ if (!C)
+ return None;
+ SmallString<128> Encoded;
+ if (index::generateUSRForType(QualType(C, 0), Ctx, Encoded))
+ return None;
+ return OpaqueType(Encoded.str());
+}
+
+OpaqueType::OpaqueType(std::string Data) : Data(std::move(Data)) {}
+
+Optional<OpaqueType> OpaqueType::fromType(ASTContext &Ctx, QualType Type) {
+ return encode(Ctx, Type);
+}
+
+Optional<OpaqueType>
+OpaqueType::fromCompletionResult(ASTContext &Ctx,
+ const CodeCompletionResult &R) {
+ auto T = typeOfCompletion(R);
+ if (!T)
+ return None;
+ return encode(Ctx, *T);
+}
+
+} // namespace clangd
+} // namespace clang
OpenPOWER on IntegriCloud