EricWF created this revision.
EricWF added reviewers: GorNishanov, rsmith, vsk, aaron.ballman.
Herald added a subscriber: modocache.

Currently an invalid source range is generated for the member call expressions 
of `co_await`. The end location of the call expression is the `co_await` token 
loc, while the start is the location of the operand. This causes crashes when 
the source range is used to produce diagnostics.

This patch fixes the issues by using the expression location instead of the 
token location when building the member calls.


Repository:
  rC Clang

https://reviews.llvm.org/D44915

Files:
  lib/Sema/SemaCoroutine.cpp
  test/SemaCXX/coroutine-source-location-crash.cpp


Index: test/SemaCXX/coroutine-source-location-crash.cpp
===================================================================
--- /dev/null
+++ test/SemaCXX/coroutine-source-location-crash.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++14 -fcoroutines-ts \
+// RUN:    -fsyntax-only -ast-dump | FileCheck %s
+#include "Inputs/std-coroutine.h"
+
+using namespace std::experimental;
+
+struct A {
+  bool await_ready();
+  void await_resume();
+  template <typename F>
+  void await_suspend(F);
+};
+
+struct coro_t {
+  struct promise_type {
+    coro_t get_return_object();
+    suspend_never initial_suspend();
+    suspend_never final_suspend();
+    void return_void();
+    static void unhandled_exception();
+  };
+};
+
+// {{0x[0-9a-fA-F]+}} <line:[[@LINE+1]]:1, col:36>
+// CHECK-LABEL: FunctionDecl {{.*}} f 'coro_t (int)'
+coro_t f(int n) {
+  A a{};
+  // CHECK: CoawaitExpr {{0x[0-9a-fA-F]+}} <col:3, col:12>
+  // CHECK-NEXT: DeclRefExpr {{0x[0-9a-fA-F]+}} <col:12>
+  // CHECK-NEXT: CXXMemberCallExpr {{0x[0-9a-fA-F]+}} <col:12>
+  // CHECK-NEXT: MemberExpr {{0x[0-9a-fA-F]+}} <col:12>
+  co_await a;
+}
Index: lib/Sema/SemaCoroutine.cpp
===================================================================
--- lib/Sema/SemaCoroutine.cpp
+++ lib/Sema/SemaCoroutine.cpp
@@ -708,9 +708,14 @@
   if (E->getValueKind() == VK_RValue)
     E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
 
+  // The location of the `co_await` token cannot be used when constructing
+  // the member call expressions since it's before the location of `Expr`, 
which
+  // is used as the start of the member call expression.
+  SourceLocation CallLoc = E->getExprLoc();
+
   // Build the await_ready, await_suspend, await_resume calls.
   ReadySuspendResumeResult RSS =
-      buildCoawaitCalls(*this, Coroutine->CoroutinePromise, Loc, E);
+      buildCoawaitCalls(*this, Coroutine->CoroutinePromise, CallLoc, E);
   if (RSS.IsInvalid)
     return ExprError();
 


Index: test/SemaCXX/coroutine-source-location-crash.cpp
===================================================================
--- /dev/null
+++ test/SemaCXX/coroutine-source-location-crash.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++14 -fcoroutines-ts \
+// RUN:    -fsyntax-only -ast-dump | FileCheck %s
+#include "Inputs/std-coroutine.h"
+
+using namespace std::experimental;
+
+struct A {
+  bool await_ready();
+  void await_resume();
+  template <typename F>
+  void await_suspend(F);
+};
+
+struct coro_t {
+  struct promise_type {
+    coro_t get_return_object();
+    suspend_never initial_suspend();
+    suspend_never final_suspend();
+    void return_void();
+    static void unhandled_exception();
+  };
+};
+
+// {{0x[0-9a-fA-F]+}} <line:[[@LINE+1]]:1, col:36>
+// CHECK-LABEL: FunctionDecl {{.*}} f 'coro_t (int)'
+coro_t f(int n) {
+  A a{};
+  // CHECK: CoawaitExpr {{0x[0-9a-fA-F]+}} <col:3, col:12>
+  // CHECK-NEXT: DeclRefExpr {{0x[0-9a-fA-F]+}} <col:12>
+  // CHECK-NEXT: CXXMemberCallExpr {{0x[0-9a-fA-F]+}} <col:12>
+  // CHECK-NEXT: MemberExpr {{0x[0-9a-fA-F]+}} <col:12>
+  co_await a;
+}
Index: lib/Sema/SemaCoroutine.cpp
===================================================================
--- lib/Sema/SemaCoroutine.cpp
+++ lib/Sema/SemaCoroutine.cpp
@@ -708,9 +708,14 @@
   if (E->getValueKind() == VK_RValue)
     E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
 
+  // The location of the `co_await` token cannot be used when constructing
+  // the member call expressions since it's before the location of `Expr`, which
+  // is used as the start of the member call expression.
+  SourceLocation CallLoc = E->getExprLoc();
+
   // Build the await_ready, await_suspend, await_resume calls.
   ReadySuspendResumeResult RSS =
-      buildCoawaitCalls(*this, Coroutine->CoroutinePromise, Loc, E);
+      buildCoawaitCalls(*this, Coroutine->CoroutinePromise, CallLoc, E);
   if (RSS.IsInvalid)
     return ExprError();
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to