diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -14962,6 +14962,12 @@ IdentifierInfo *Name = FD->getIdentifier(); if (!Name) return; + + if (getLangOpts().Coroutines && Name->isStr("pthread_self") && + FD->hasAttr()) { + FD->dropAttr(); + } + if ((!getLangOpts().CPlusPlus && FD->getDeclContext()->isTranslationUnit()) || (isa(FD->getDeclContext()) && diff --git a/clang/test/CodeGenCoroutines/coro-pthread_self.cpp b/clang/test/CodeGenCoroutines/coro-pthread_self.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCoroutines/coro-pthread_self.cpp @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines-ts -std=c++14 -O3 -emit-llvm %s -o - | FileCheck %s + +#include "Inputs/coroutine.h" + +namespace coro = std::experimental::coroutines_v1; + +typedef void *pthread_t; +pthread_t pthread_self(void) __attribute__((__const__)); + +struct awaitable { + bool await_ready() { return false; } + void await_suspend(coro::coroutine_handle<> h); + void await_resume() {} +}; +awaitable switch_to_new_thread(); + +struct task { + struct promise_type { + task get_return_object() { return {}; } + coro::suspend_never initial_suspend() { return {}; } + coro::suspend_never final_suspend() noexcept { return {}; } + void return_void() {} + void unhandled_exception() {} + }; +}; + +void check(pthread_t p1, pthread_t p2); + +task resuming_on_new_thread() { + auto pthread1 = pthread_self(); + co_await switch_to_new_thread(); + auto pthread2 = pthread_self(); + check(pthread1, pthread2); +} + +void non_coroutine() { + auto pthread1 = pthread_self(); + check(pthread1, pthread1); + auto pthread2 = pthread_self(); + check(pthread1, pthread2); +} + +// CHECK-LABEL: define void @_Z13non_coroutinev() +// CHECK-NEXT: entry: +// CHECK-NEXT: %call = tail call i8* @_Z12pthread_selfv() +// CHECK-NEXT: tail call void @_Z5checkPvS_(i8* %call, i8* %call) +// CHECK-NEXT: %call1 = tail call i8* @_Z12pthread_selfv() +// CHECK-NEXT: tail call void @_Z5checkPvS_(i8* %call, i8* %call1) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define internal fastcc void @_Z22resuming_on_new_threadv.resume +// CHECK: %[[RELOAD_ADDR:.+.reload.addr]] = getelementptr inbounds %_Z22resuming_on_new_threadv.Frame, %_Z22resuming_on_new_threadv.Frame* %FramePtr, i64 0, i32 {{.+}} +// CHECK: %[[RELOAD:.+]] = load i8*, i8** %[[RELOAD_ADDR]], align 8 +// CHECK: %[[CALL:.+]] = tail call i8* @_Z12pthread_selfv() +// CHECK: tail call void @_Z5checkPvS_(i8* %[[RELOAD]], i8* %[[CALL]])