]> granicus.if.org Git - clang/commitdiff
Ignore const/volatile/restrict qualifiers on anonymous structs and
authorDouglas Gregor <dgregor@apple.com>
Mon, 9 May 2011 23:05:33 +0000 (23:05 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 9 May 2011 23:05:33 +0000 (23:05 +0000)
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
include/clang/Sema/DeclSpec.h
lib/Sema/SemaDecl.cpp
test/SemaCXX/anonymous-union.cpp

index 6d90ba17c615a807edfc6b8534792ca6e0ca8a85..1e546867e4bfafac72050e64a68696da9c1932aa 100644 (file)
@@ -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)">;
index 8179b63f459226e8d301dde2d29cec2cb4ef4eca..da40f14f0ed772f10799a6809a9cb1267d5c56da 100644 (file)
@@ -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; }
index cd6dc9227ee8955b98349b09012022af63be24cc..15f168117d22d7849bb39ecabb98cabea5b9cff2 100644 (file)
@@ -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
index 553ae658e53b3e247d88f9178e2872839de15c26..2dd7ab86a88d76a011d0af0f5bb028a543135d23 100644 (file)
@@ -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;
+}