aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Frontend/ASTUnit.h3
-rw-r--r--include/clang/Sema/CodeCompleteConsumer.h59
-rw-r--r--lib/Frontend/ASTUnit.cpp24
-rw-r--r--lib/Sema/SemaCodeComplete.cpp45
-rw-r--r--test/Index/complete-exprs.c2
-rw-r--r--test/Index/complete-macros.c2
6 files changed, 98 insertions, 37 deletions
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 76a86871de..f18e70e750 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -232,6 +232,9 @@ public:
/// \brief The libclang cursor kind corresponding to this code-completion
/// result.
CXCursorKind Kind;
+
+ /// \brief The simplified type class for a non-macro completion result.
+ SimplifiedTypeClass TypeClass;
};
private:
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index 16dd69d401..82ea46c290 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/include/clang/Sema/CodeCompleteConsumer.h
@@ -14,6 +14,7 @@
#define LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
#include "clang/AST/Type.h"
+#include "clang/AST/CanonicalType.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "clang-c/Index.h"
@@ -72,7 +73,38 @@ enum {
/// Objective-C object pointer types).
CCF_SimilarTypeMatch = 2
};
+
+/// \brief A simplified classification of types used when determining
+/// "similar" types for code completion.
+enum SimplifiedTypeClass {
+ STC_Arithmetic,
+ STC_Array,
+ STC_Block,
+ STC_Function,
+ STC_ObjectiveC,
+ STC_Other,
+ STC_Pointer,
+ STC_Record,
+ STC_Void
+};
+
+/// \brief Determine the simplified type class of the given canonical type.
+SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T);
+/// \brief Determine the type that this declaration will have if it is used
+/// as a type or in an expression.
+QualType getDeclUsageType(ASTContext &C, NamedDecl *ND);
+
+/// \brief Determine the priority to be given to a macro code completion result
+/// with the given name.
+///
+/// \param MacroName The name of the macro.
+///
+/// \param PreferredTypeIsPointer Whether the preferred type for the context
+/// of this macro is a pointer type.
+unsigned getMacroUsagePriority(llvm::StringRef MacroName,
+ bool PreferredTypeIsPointer = false);
+
class FunctionDecl;
class FunctionType;
class FunctionTemplateDecl;
@@ -138,29 +170,36 @@ public:
private:
enum Kind Kind;
+ /// \brief The type that would prefer to see at this point (e.g., the type
+ /// of an initializer or function parameter).
+ QualType PreferredType;
+
/// \brief The type of the base object in a member access expression.
- QualType Type;
+ QualType BaseType;
public:
/// \brief Construct a new code-completion context of the given kind.
- CodeCompletionContext(enum Kind Kind) : Kind(Kind) {
- assert(Kind != CCC_MemberAccess && "Member access requires a type");
- }
+ CodeCompletionContext(enum Kind Kind) : Kind(Kind) { }
/// \brief Construct a new code-completion context of the given kind.
- CodeCompletionContext(enum Kind Kind, QualType T) : Kind(Kind), Type(T) {
- assert(Kind == CCC_MemberAccess && "Only member access has a type");
+ CodeCompletionContext(enum Kind Kind, QualType T) : Kind(Kind) {
+ if (Kind == CCC_MemberAccess)
+ BaseType = T;
+ else
+ PreferredType = T;
}
/// \brief Retrieve the kind of code-completion context.
enum Kind getKind() const { return Kind; }
+ /// \brief Retrieve the type that this expression would prefer to have, e.g.,
+ /// if the expression is a variable initializer or a function argument, the
+ /// type of the corresponding variable or function parameter.
+ QualType getPreferredType() const { return PreferredType; }
+
/// \brief Retrieve the type of the base object in a member-access
/// expression.
- QualType getType() const {
- assert(Kind == CCC_MemberAccess && "Only member access has a type");
- return Type;
- }
+ QualType getBaseType() const { return BaseType; }
};
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 8ac5b681a6..a573fb41ab 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -191,6 +191,10 @@ void ASTUnit::CacheCodeCompletionResults() {
Ctx->getLangOptions());
CachedResult.Priority = Results[I].Priority;
CachedResult.Kind = Results[I].CursorKind;
+ CachedResult.TypeClass
+ = getSimplifiedTypeClass(
+ Ctx->getCanonicalType(getDeclUsageType(*Ctx,
+ Results[I].Declaration)));
CachedCompletionResults.push_back(CachedResult);
break;
}
@@ -215,6 +219,7 @@ void ASTUnit::CacheCodeCompletionResults() {
| (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
CachedResult.Priority = Results[I].Priority;
CachedResult.Kind = Results[I].CursorKind;
+ CachedResult.TypeClass = STC_Void;
CachedCompletionResults.push_back(CachedResult);
break;
}
@@ -1417,7 +1422,24 @@ namespace {
AddedResult = true;
}
- AllResults.push_back(Result(C->Completion, C->Priority, C->Kind));
+ // Adjust priority based on similar type classes.
+ unsigned Priority = C->Priority;
+ if (!Context.getPreferredType().isNull()) {
+ if (C->Kind == CXCursor_MacroDefinition) {
+ Priority = getMacroUsagePriority(C->Completion->getTypedText(),
+ Context.getPreferredType()->isAnyPointerType());
+ } else {
+ CanQualType Expected
+ = S.Context.getCanonicalType(Context.getPreferredType());
+ SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected);
+ if (ExpectedSTC == C->TypeClass) {
+ // FIXME: How can we check for an exact match?
+ Priority /= CCF_SimilarTypeMatch;
+ }
+ }
+ }
+
+ AllResults.push_back(Result(C->Completion, Priority, C->Kind));
}
// If we did not add any cached completion results, just forward the
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 599a10fd90..332f8c8029 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -476,21 +476,9 @@ bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
return false;
}
-enum SimplifiedTypeClass {
- STC_Arithmetic,
- STC_Array,
- STC_Block,
- STC_Function,
- STC_ObjectiveC,
- STC_Other,
- STC_Pointer,
- STC_Record,
- STC_Void
-};
-
/// \brief A simplified classification of types used to determine whether two
/// types are "similar enough" when adjusting priorities.
-static SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T) {
+SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
switch (T->getTypeClass()) {
case Type::Builtin:
switch (cast<BuiltinType>(T)->getKind()) {
@@ -561,7 +549,7 @@ static SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T) {
/// \brief Get the type that a given expression will have if this declaration
/// is used as an expression in its "typical" code-completion form.
-static QualType getDeclUsageType(ASTContext &C, NamedDecl *ND) {
+QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) {
ND = cast<NamedDecl>(ND->getUnderlyingDecl());
if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
@@ -2202,6 +2190,20 @@ namespace {
};
}
+unsigned clang::getMacroUsagePriority(llvm::StringRef MacroName,
+ bool PreferredTypeIsPointer) {
+ unsigned Priority = CCP_Macro;
+
+ // Treat the "nil" and "NULL" macros as null pointer constants.
+ if (MacroName.equals("nil") || MacroName.equals("NULL")) {
+ Priority = CCP_Constant;
+ if (PreferredTypeIsPointer)
+ Priority = Priority / CCF_SimilarTypeMatch;
+ }
+
+ return Priority;
+}
+
static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
bool TargetTypeIsPointer = false) {
typedef CodeCompleteConsumer::Result Result;
@@ -2210,16 +2212,9 @@ static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
for (Preprocessor::macro_iterator M = PP.macro_begin(),
MEnd = PP.macro_end();
M != MEnd; ++M) {
- unsigned Priority = CCP_Macro;
-
- // Treat the "nil" and "NULL" macros as null pointer constants.
- if (M->first->isStr("nil") || M->first->isStr("NULL")) {
- Priority = CCP_Constant;
- if (TargetTypeIsPointer)
- Priority = Priority / CCF_SimilarTypeMatch;
- }
-
- Results.AddResult(Result(M->first, Priority));
+ Results.AddResult(Result(M->first,
+ getMacroUsagePriority(M->first->getName(),
+ TargetTypeIsPointer)));
}
Results.ExitScope();
}
@@ -2356,7 +2351,7 @@ void Sema::CodeCompleteExpression(Scope *S, QualType T,
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, PreferredTypeIsPointer);
HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Expression,
+ CodeCompletionContext(CodeCompletionContext::CCC_Expression, T),
Results.data(),Results.size());
}
diff --git a/test/Index/complete-exprs.c b/test/Index/complete-exprs.c
index 7dfe280d9e..3605420956 100644
--- a/test/Index/complete-exprs.c
+++ b/test/Index/complete-exprs.c
@@ -23,7 +23,7 @@ const char *str = "Hello, \nWorld";
// FIXME: Priorities aren't right
// CHECK-CC1a: ParmDecl:{ResultType int}{TypedText j} (2)
// CHECK-CC1a: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
-// CHECK-CC1a: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50)
+// CHECK-CC1a: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (25)
// CHECK-CC1a: macro definition:{TypedText __VERSION__} (70)
// RUN: c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
// RUN: env CINDEXTEST_EDITING=1 c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
diff --git a/test/Index/complete-macros.c b/test/Index/complete-macros.c
index d0974db31f..26a63b151b 100644
--- a/test/Index/complete-macros.c
+++ b/test/Index/complete-macros.c
@@ -20,6 +20,8 @@ void f2() {
// CHECK-CC1: macro definition:{TypedText FOO}{LeftParen (}{Placeholder Arg1}{Comma , }{Placeholder Arg2}{RightParen )}
// RUN: c-index-test -code-completion-at=%s:13:13 %s | FileCheck -check-prefix=CHECK-CC2 %s
// RUN: c-index-test -code-completion-at=%s:14:8 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:14:8 %s | FileCheck -check-prefix=CHECK-CC2 %s
// CHECK-CC2: macro definition:{TypedText nil} (30)
// RUN: c-index-test -code-completion-at=%s:15:5 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:15:5 %s | FileCheck -check-prefix=CHECK-CC3 %s
// CHECK-CC3: macro definition:{TypedText nil} (60)