From 7604f64a865bdba86c05cab76bcd47fd10372eb8 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 9 May 2011 23:05:33 +0000 Subject: [PATCH] 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 --- include/clang/Basic/DiagnosticSemaKinds.td | 4 ++- include/clang/Sema/DeclSpec.h | 8 ++++++ lib/Sema/SemaDecl.cpp | 18 +++++++++++++ test/SemaCXX/anonymous-union.cpp | 30 +++++++++++++++++++--- 4 files changed, 55 insertions(+), 5 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 6d90ba17c6..1e546867e4 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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)">; diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 8179b63f45..da40f14f0e 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -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; } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index cd6dc9227e..15f168117d 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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 diff --git a/test/SemaCXX/anonymous-union.cpp b/test/SemaCXX/anonymous-union.cpp index 553ae658e5..2dd7ab86a8 100644 --- a/test/SemaCXX/anonymous-union.cpp +++ b/test/SemaCXX/anonymous-union.cpp @@ -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 { // 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 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 baz; +} -- 2.40.0