]> granicus.if.org Git - clang/commitdiff
[CodeComplete] Fix assertion failure
authorIlya Biryukov <ibiryukov@google.com>
Fri, 7 Dec 2018 13:17:52 +0000 (13:17 +0000)
committerIlya Biryukov <ibiryukov@google.com>
Fri, 7 Dec 2018 13:17:52 +0000 (13:17 +0000)
Summary:
...that fires when running completion inside an argument of
UnresolvedMemberExpr (see the added test).

The assertion that fires is from Sema::TryObjectArgumentInitialization:

    assert(FromClassification.isLValue());

This happens because Sema::AddFunctionCandidates does not account for
object types which are pointers. It ends up classifying them incorrectly.
All usages of the function outside code completion are used to run
overload resolution for operators. In those cases the object type being
passed is always a non-pointer type, so it's not surprising the function
did not expect a pointer in the object argument.

However, code completion reuses the same function and calls it with the
object argument coming from UnresolvedMemberExpr, which can be a pointer
if the member expr is an arrow ('->') access.

Extending AddFunctionCandidates to allow pointer object types does not
seem too crazy since all the functions down the call chain can properly
handle pointer object types if we properly classify the object argument
as an l-value, i.e. the classification of the implicitly dereferenced
pointer.

Reviewers: kadircet

Reviewed By: kadircet

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D55331

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@348590 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaOverload.cpp
test/CodeCompletion/signatures-crash.cpp [new file with mode: 0644]

index 614b83d5248b67879ee1e1038ee15b61d8d9d77e..928a982e1fc7e62a16949e0ef2fae614ad07ce69 100644 (file)
@@ -6429,7 +6429,12 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
         if (Expr *E = Args[0]) {
           // Use the explicit base to restrict the lookup:
           ObjectType = E->getType();
-          ObjectClassification = E->Classify(Context);
+          // Pointers in the object arguments are implicitly dereferenced, so we
+          // always classify them as l-values.
+          if (!ObjectType.isNull() && ObjectType->isPointerType())
+            ObjectClassification = Expr::Classification::makeSimpleLValue();
+          else
+            ObjectClassification = E->Classify(Context);
         } // .. else there is an implicit base.
         FunctionArgs = Args.slice(1);
       }
diff --git a/test/CodeCompletion/signatures-crash.cpp b/test/CodeCompletion/signatures-crash.cpp
new file mode 100644 (file)
index 0000000..c58ae0c
--- /dev/null
@@ -0,0 +1,15 @@
+struct map {
+  void find(int);
+  void find();
+};
+
+int main() {
+  map *m;
+  m->find(10);
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:8:11 %s -o - | FileCheck %s
+  // CHECK: OVERLOAD: [#void#]find(<#int#>)
+
+  // Also check when the lhs is an explicit pr-value.
+  (m+0)->find(10);
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:13:15 %s -o - | FileCheck %s
+}