[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
This commit is contained in:
Andrew Savonichev 2018-10-29 11:14:01 +00:00
parent 7a0841ef2f
commit 52d674d974
3 changed files with 53 additions and 34 deletions

View File

@ -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.

View File

@ -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
// 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
#if defined(HEADER) && !defined(INCLUDED)
#define INCLUDED
// 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
#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
#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

View File

@ -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