Reject forbidden storage class specifiers in OpenCL. Patch by George Russell!
llvm-svn: 125399
This commit is contained in:
parent
a49a02a04f
commit
de32b20bdd
|
@ -443,5 +443,9 @@ def warn_pragma_unused_expected_var : Warning<
|
|||
def warn_pragma_unused_expected_punc : Warning<
|
||||
"expected ')' or ',' in '#pragma unused'">;
|
||||
|
||||
// OpenCL Section 6.8.g
|
||||
def err_not_opencl_storage_class_specifier : Error<
|
||||
"OpenCL does not support the '%0' storage class specifier">;
|
||||
|
||||
} // end of Parse Issue category.
|
||||
} // end of Parser diagnostics
|
||||
|
|
|
@ -403,7 +403,7 @@ public:
|
|||
/// TODO: use a more general approach that still allows these
|
||||
/// diagnostics to be ignored when desired.
|
||||
bool SetStorageClassSpec(SCS S, SourceLocation Loc, const char *&PrevSpec,
|
||||
unsigned &DiagID);
|
||||
unsigned &DiagID, const LangOptions &Lang);
|
||||
bool SetStorageClassSpecThread(SourceLocation Loc, const char *&PrevSpec,
|
||||
unsigned &DiagID);
|
||||
bool SetTypeSpecWidth(TSW W, SourceLocation Loc, const char *&PrevSpec,
|
||||
|
|
|
@ -1204,23 +1204,23 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
|||
// storage-class-specifier
|
||||
case tok::kw_typedef:
|
||||
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec,
|
||||
DiagID);
|
||||
DiagID, getLang());
|
||||
break;
|
||||
case tok::kw_extern:
|
||||
if (DS.isThreadSpecified())
|
||||
Diag(Tok, diag::ext_thread_before) << "extern";
|
||||
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, Loc, PrevSpec,
|
||||
DiagID);
|
||||
DiagID, getLang());
|
||||
break;
|
||||
case tok::kw___private_extern__:
|
||||
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_private_extern, Loc,
|
||||
PrevSpec, DiagID);
|
||||
PrevSpec, DiagID, getLang());
|
||||
break;
|
||||
case tok::kw_static:
|
||||
if (DS.isThreadSpecified())
|
||||
Diag(Tok, diag::ext_thread_before) << "static";
|
||||
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, Loc, PrevSpec,
|
||||
DiagID);
|
||||
DiagID, getLang());
|
||||
break;
|
||||
case tok::kw_auto:
|
||||
if (getLang().CPlusPlus0x)
|
||||
|
@ -1228,15 +1228,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
|||
DiagID);
|
||||
else
|
||||
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec,
|
||||
DiagID);
|
||||
DiagID, getLang());
|
||||
break;
|
||||
case tok::kw_register:
|
||||
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, Loc, PrevSpec,
|
||||
DiagID);
|
||||
DiagID, getLang());
|
||||
break;
|
||||
case tok::kw_mutable:
|
||||
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_mutable, Loc, PrevSpec,
|
||||
DiagID);
|
||||
DiagID, getLang());
|
||||
break;
|
||||
case tok::kw___thread:
|
||||
isInvalid = DS.SetStorageClassSpecThread(Loc, PrevSpec, DiagID);
|
||||
|
|
|
@ -226,7 +226,25 @@ const char *DeclSpec::getSpecifierName(TQ T) {
|
|||
|
||||
bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc,
|
||||
const char *&PrevSpec,
|
||||
unsigned &DiagID) {
|
||||
unsigned &DiagID,
|
||||
const LangOptions &Lang) {
|
||||
// OpenCL prohibits extern, auto, register, and static
|
||||
// It seems sensible to prohibit private_extern too
|
||||
if (Lang.OpenCL) {
|
||||
switch (S) {
|
||||
case SCS_extern:
|
||||
case SCS_private_extern:
|
||||
case SCS_auto:
|
||||
case SCS_register:
|
||||
case SCS_static:
|
||||
DiagID = diag::err_not_opencl_storage_class_specifier;
|
||||
PrevSpec = getSpecifierName(S);
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (StorageClassSpec != SCS_unspecified) {
|
||||
// Changing storage class is allowed only if the previous one
|
||||
// was the 'extern' that is part of a linkage specification and
|
||||
|
|
|
@ -1922,7 +1922,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
|
|||
|
||||
// Recover by adding 'static'.
|
||||
DS.SetStorageClassSpec(DeclSpec::SCS_static, SourceLocation(),
|
||||
PrevSpec, DiagID);
|
||||
PrevSpec, DiagID, getLangOptions());
|
||||
}
|
||||
// C++ [class.union]p3:
|
||||
// A storage class is not allowed in a declaration of an
|
||||
|
@ -1935,7 +1935,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
|
|||
|
||||
// Recover by removing the storage specifier.
|
||||
DS.SetStorageClassSpec(DeclSpec::SCS_unspecified, SourceLocation(),
|
||||
PrevSpec, DiagID);
|
||||
PrevSpec, DiagID, getLangOptions());
|
||||
}
|
||||
|
||||
// C++ [class.union]p2:
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
// RUN: %clang_cc1 %s -x cl -verify -fsyntax-only
|
||||
|
||||
void test_storage_class_specs()
|
||||
{
|
||||
static int a; // expected-error {{OpenCL does not support the 'static' storage class specifier}}
|
||||
register int b; // expected-error {{OpenCL does not support the 'register' storage class specifier}}
|
||||
extern int c; // expected-error {{OpenCL does not support the 'extern' storage class specifier}}
|
||||
auto int d; // expected-error {{OpenCL does not support the 'auto' storage class specifier}}
|
||||
}
|
|
@ -28,7 +28,7 @@ execute_external = platform.system() != 'Windows'
|
|||
config.test_format = lit.formats.ShTest(execute_external)
|
||||
|
||||
# suffixes: A list of file extensions to treat as test files.
|
||||
config.suffixes = ['.c', '.cpp', '.m', '.mm', '.cu', '.ll']
|
||||
config.suffixes = ['.c', '.cpp', '.m', '.mm', '.cu', '.ll', '.cl']
|
||||
|
||||
# test_source_root: The root path where tests are located.
|
||||
config.test_source_root = os.path.dirname(__file__)
|
||||
|
|
Loading…
Reference in New Issue