Skip to content

Commit

Permalink
Merging r345497:
Browse files Browse the repository at this point in the history
------------------------------------------------------------------------
r345497 | asavonic | 2018-10-29 04:14:01 -0700 (Mon, 29 Oct 2018) | 29 lines

[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: 347834
  • Loading branch information
tstellar committed Nov 29, 2018
1 parent 3e4d4dd commit 3ccd033
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 36 deletions.
5 changes: 4 additions & 1 deletion clang/lib/Serialization/ASTWriter.cpp
Expand Up @@ -5022,13 +5022,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.
Expand Down
60 changes: 25 additions & 35 deletions 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) {
Expand All @@ -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 disabled due to OpenCL extension}}
// expected-note@-22 {{candidate function not viable: requires 0 arguments, but 1 was provided}}
// expected-note@extension-begin.h:18 {{candidate disabled due to OpenCL extension}}
// expected-note@extension-begin.h:23 {{candidate function not viable: requires 0 arguments, but 1 was provided}}
}

#endif // HEADER_USER

26 changes: 26 additions & 0 deletions 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

0 comments on commit 3ccd033

Please sign in to comment.