Ignore const/volatile/restrict qualifiers on anonymous structs and

unions. Fixes PR8326.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131109 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2011-05-09 23:05:33 +00:00
Родитель 4b7e048970
Коммит 7604f64a86
4 изменённых файлов: 55 добавлений и 5 удалений

Просмотреть файл

@ -758,7 +758,9 @@ def err_static_data_member_not_allowed_in_union_or_anon_struct : Error<
"static data member %0 not allowed in %select{anonymous struct|union}1">;
def err_union_member_of_reference_type : Error<
"union member %0 has reference type %1">;
def ext_anonymous_struct_union_qualified : Extension<
"anonymous %select{struct|union}0 cannot be '%select{const|volatile|"
"restrict}1'">;
def err_different_return_type_for_overriding_virtual_function : Error<
"virtual function %0 has a different return type (%1) than the "
"function it overrides (which has return type %2)">;

Просмотреть файл

@ -462,6 +462,14 @@ public:
SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; }
SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; }
/// \brief Clear out all of the type qualifiers.
void ClearTypeQualifiers() {
TypeQualifiers = 0;
TQ_constLoc = SourceLocation();
TQ_restrictLoc = SourceLocation();
TQ_volatileLoc = SourceLocation();
}
// function-specifier
bool isInlineSpecified() const { return FS_inline_specified; }
SourceLocation getInlineSpecLoc() const { return FS_inlineLoc; }

Просмотреть файл

@ -2489,6 +2489,24 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
PrevSpec, DiagID, getLangOptions());
}
// Ignore const/volatile/restrict qualifiers.
if (DS.getTypeQualifiers()) {
if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
Diag(DS.getConstSpecLoc(), diag::ext_anonymous_struct_union_qualified)
<< Record->isUnion() << 0
<< FixItHint::CreateRemoval(DS.getConstSpecLoc());
if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
Diag(DS.getVolatileSpecLoc(), diag::ext_anonymous_struct_union_qualified)
<< Record->isUnion() << 1
<< FixItHint::CreateRemoval(DS.getVolatileSpecLoc());
if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
Diag(DS.getRestrictSpecLoc(), diag::ext_anonymous_struct_union_qualified)
<< Record->isUnion() << 2
<< FixItHint::CreateRemoval(DS.getRestrictSpecLoc());
DS.ClearTypeQualifiers();
}
// C++ [class.union]p2:
// The member-specification of an anonymous union shall only
// define non-static data members. [Note: nested types and

Просмотреть файл

@ -1,4 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s
struct X {
union {
float f3;
@ -17,7 +17,7 @@ struct X {
void test_unqual_references();
struct {
struct { // expected-warning{{anonymous structs are a GNU extension}}
int a;
float b;
};
@ -125,7 +125,7 @@ typedef struct _s {
// <rdar://problem/7987650>
namespace test4 {
class A {
struct {
struct { // expected-warning{{anonymous structs are a GNU extension}}
int s0; // expected-note {{declared private here}}
double s1; // expected-note {{declared private here}}
union {
@ -136,7 +136,7 @@ namespace test4 {
union {
int u0; // expected-note {{declared private here}}
double u1; // expected-note {{declared private here}}
struct {
struct { // expected-warning{{anonymous structs are a GNU extension}}
int us0; // expected-note {{declared private here}}
double us1; // expected-note {{declared private here}}
};
@ -175,3 +175,25 @@ void foo_PR6741() {
};
}
}
namespace PR8326 {
template <class T>
class Foo {
public:
Foo()
: x(0)
, y(1){
}
private:
const union { // expected-warning{{anonymous union cannot be 'const'}}
struct { // expected-warning{{anonymous structs are a GNU extension}}
T x;
T y;
};
T v[2];
};
};
Foo<int> baz;
}