From 52d674d97499325d2c77dbcb67262c0cd1cde0b2 Mon Sep 17 00:00:00 2001 From: Andrew Savonichev Date: Mon, 29 Oct 2018 11:14:01 +0000 Subject: [PATCH] [OpenCL] Fix serialization of OpenCLExtensionDecls Summary: I recently discovered that adding the following code into `opencl-c.h` causes failure of `test/Headers/opencl-c-header.cl`: ``` #pragma OPENCL EXTENSION cl_my_ext : begin void cl_my_ext_foobarbaz(); #pragma OPENCL EXTENSIOn cl_my_ext : end ``` Clang crashes at the assertion is `ASTReader::getGlobalSubmoduleID()`: ``` assert(I != M.SubmoduleRemap.end() && "Invalid index into submodule index remap"); ``` The root cause of the problem that to deserialize `OPENCL_EXTENSION_DECLS` section `ASTReader` needs to deserialize a Decl contained in it. In turn, deserializing a Decl requires information about whether this declaration is part of a (sub)module, but this information is not read yet because it is located further in a module file. Reviewers: Anastasia, yaxunl, JDevlieghere Reviewed By: Anastasia Subscribers: sidorovd, cfe-commits, asavonic Differential Revision: https://reviews.llvm.org/D53200 llvm-svn: 345497 --- clang/lib/Serialization/ASTWriter.cpp | 5 ++- clang/test/SemaOpenCL/extension-begin.cl | 60 +++++++++++++------------------- clang/test/SemaOpenCL/extension-begin.h | 26 ++++++++++++++ 3 files changed, 55 insertions(+), 36 deletions(-) create mode 100644 clang/test/SemaOpenCL/extension-begin.h diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 06df715..eb20751 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -5014,13 +5014,16 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, WriteFPPragmaOptions(SemaRef.getFPOptions()); WriteOpenCLExtensions(SemaRef); WriteOpenCLExtensionTypes(SemaRef); - WriteOpenCLExtensionDecls(SemaRef); WriteCUDAPragmas(SemaRef); // If we're emitting a module, write out the submodule information. if (WritingModule) WriteSubmodules(WritingModule); + // We need to have information about submodules to correctly deserialize + // decls from OpenCLExtensionDecls block + WriteOpenCLExtensionDecls(SemaRef); + Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes); // Write the record containing external, unnamed definitions. diff --git a/clang/test/SemaOpenCL/extension-begin.cl b/clang/test/SemaOpenCL/extension-begin.cl index 440e72c..4910aeb 100644 --- a/clang/test/SemaOpenCL/extension-begin.cl +++ b/clang/test/SemaOpenCL/extension-begin.cl @@ -1,37 +1,29 @@ // Test this without pch. -// RUN: %clang_cc1 %s -DHEADER -DHEADER_USER -triple spir-unknown-unknown -verify -pedantic -fsyntax-only +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only // Test with pch. -// RUN: %clang_cc1 %s -DHEADER -triple spir-unknown-unknown -emit-pch -o %t -verify -pedantic -// RUN: %clang_cc1 %s -DHEADER_USER -triple spir-unknown-unknown -include-pch %t -fsyntax-only -verify -pedantic - -#if defined(HEADER) && !defined(INCLUDED) -#define INCLUDED - -#pragma OPENCL EXTENSION all : begin // expected-warning {{expected 'disable' - ignoring}} -#pragma OPENCL EXTENSION all : end // expected-warning {{expected 'disable' - ignoring}} - -#pragma OPENCL EXTENSION my_ext : begin - -struct A { - int a; -}; - -typedef struct A TypedefOfA; -typedef const TypedefOfA* PointerOfA; - -void f(void); - -__attribute__((overloadable)) void g(long x); - -#pragma OPENCL EXTENSION my_ext : end -#pragma OPENCL EXTENSION my_ext : end // expected-warning {{OpenCL extension end directive mismatches begin directive - ignoring}} - -__attribute__((overloadable)) void g(void); - -#endif // defined(HEADER) && !defined(INCLUDED) - -#ifdef HEADER_USER +// RUN: %clang_cc1 -x cl %S/extension-begin.h -triple spir-unknown-unknown -emit-pch -o %t.pch -pedantic +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -include-pch %t.pch -DIMPLICIT_INCLUDE -DUSE_PCH -fsyntax-only -verify -pedantic + +// Test with modules +// RUN: rm -rf %t.modules +// RUN: mkdir -p %t.modules +// +// RUN: %clang_cc1 -cl-std=CL1.2 -DIMPLICIT_INCLUDE -include %S/extension-begin.h -triple spir-unknown-unknown -O0 -emit-llvm -o - -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.modules %s -verify -pedantic +// +// RUN: rm -rf %t.modules +// RUN: mkdir -p %t.modules +// +// RUN: %clang_cc1 -cl-std=CL2.0 -DIMPLICIT_INCLUDE -include %S/extension-begin.h -triple spir-unknown-unknown -O0 -emit-llvm -o - -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.modules %s -verify -pedantic + +#ifndef IMPLICIT_INCLUDE +#include "extension-begin.h" +#endif // IMPLICIT_INCLUDE +#ifndef USE_PCH +// expected-warning@extension-begin.h:4 {{expected 'disable' - ignoring}} +// expected-warning@extension-begin.h:5 {{expected 'disable' - ignoring}} +// expected-warning@extension-begin.h:21 {{OpenCL extension end directive mismatches begin directive - ignoring}} +#endif // USE_PCH #pragma OPENCL EXTENSION my_ext : enable void test_f1(void) { @@ -48,9 +40,7 @@ void test_f2(void) { PointerOfA test_A_pointer; // expected-error {{use of type 'PointerOfA' (aka 'const struct A *') requires my_ext extension to be enabled}} f(); // expected-error {{use of declaration 'f' requires my_ext extension to be enabled}} g(0); // expected-error {{no matching function for call to 'g'}} - // expected-note@-26 {{candidate unavailable as it requires OpenCL extension 'my_ext' to be disabled}} - // expected-note@-22 {{candidate function not viable: requires 0 arguments, but 1 was provided}} + // expected-note@extension-begin.h:18 {{candidate unavailable as it requires OpenCL extension 'my_ext' to be disabled}} + // expected-note@extension-begin.h:23 {{candidate function not viable: requires 0 arguments, but 1 was provided}} } -#endif // HEADER_USER - diff --git a/clang/test/SemaOpenCL/extension-begin.h b/clang/test/SemaOpenCL/extension-begin.h new file mode 100644 index 0000000..d9865ba --- /dev/null +++ b/clang/test/SemaOpenCL/extension-begin.h @@ -0,0 +1,26 @@ +#ifndef INCLUDED +#define INCLUDED + +#pragma OPENCL EXTENSION all : begin +#pragma OPENCL EXTENSION all : end + +#pragma OPENCL EXTENSION my_ext : begin + +struct A { + int a; +}; + +typedef struct A TypedefOfA; +typedef const __private TypedefOfA* PointerOfA; + +void f(void); + +__attribute__((overloadable)) void g(long x); + +#pragma OPENCL EXTENSION my_ext : end +#pragma OPENCL EXTENSION my_ext : end + +__attribute__((overloadable)) void g(void); + +#endif // INCLUDED + -- 2.7.4