[cfe-commits] r139102 - in /cfe/trunk: include/clang/Basic/ lib/Parse/ lib/Sema/ test/CXX/class/class.friend/ test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/ test/Misc/ test/SemaCXX/

Richard Smith richard-llvm at metafoo.co.uk
Sun Sep 4 12:54:14 PDT 2011


Author: rsmith
Date: Sun Sep  4 14:54:14 2011
New Revision: 139102

URL: http://llvm.org/viewvc/llvm-project?rev=139102&view=rev
Log:
PR10458: Finesse behaviour of C++0x features when in pre-0x mode. Accept for-range and auto with an ExtWarn, and produce a -Wc++0x-compat warning in C++98 mode when auto is used as a storage class.

Added:
    cfe/trunk/test/SemaCXX/PR10458.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseStmt.cpp
    cfe/trunk/lib/Sema/DeclSpec.cpp
    cfe/trunk/test/CXX/class/class.friend/p6.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp
    cfe/trunk/test/Misc/warning-flags.c
    cfe/trunk/test/SemaCXX/auto-cxx0x.cpp
    cfe/trunk/test/SemaCXX/auto-cxx98.cpp
    cfe/trunk/test/SemaCXX/class.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=139102&r1=139101&r2=139102&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Sun Sep  4 14:54:14 2011
@@ -28,10 +28,6 @@
 def ext_extra_ivar_semi : Extension<
   "extra ';' inside instance variable list">;
 
-def auto_storage_class : ExtWarn<
-  "'auto' storage class specifier is redundant and will be "
-  "removed in future releases">;
-
 def ext_duplicate_declspec : Extension<"duplicate '%0' declaration specifier">;
 def ext_plain_complex : ExtWarn<
   "plain '_Complex' requires a type specifier; assuming '_Complex double'">;
@@ -198,6 +194,16 @@
 def ext_generalized_initializer_lists : ExtWarn<
   "generalized initializer lists are a C++0x extension unsupported in Clang">,
   InGroup<CXX0x>;
+def ext_auto_type_specifier : ExtWarn<
+  "'auto' type specifier is a C++0x extension">, InGroup<CXX0x>;
+def warn_auto_storage_class : Warning<
+  "'auto' storage class specifier is redundant and incompatible with C++0x">,
+  InGroup<CXX0xCompat>;
+def ext_auto_storage_class : ExtWarn<
+  "'auto' storage class specifier is not permitted in C++0x, and will not "
+  "be supported in future releases">;
+def ext_for_range : ExtWarn<
+  "range-based for loop is a C++0x extension">, InGroup<CXX0x>;
 def err_argument_required_after_attribute : Error<
   "argument required after attribute">;
 def err_missing_param : Error<"expected parameter declarator">;

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=139102&r1=139101&r2=139102&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Sun Sep  4 14:54:14 2011
@@ -1769,16 +1769,14 @@
       if (getLang().CPlusPlus0x) {
         if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
           isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec,
-                                           DiagID, getLang());
+                                             DiagID, getLang());
           if (!isInvalid)
-            Diag(Tok, diag::auto_storage_class)
+            Diag(Tok, diag::ext_auto_storage_class)
               << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
-        }
-        else
+        } else
           isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec,
                                          DiagID);
-      }
-      else
+      } else
         isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec,
                                            DiagID, getLang());
       break;

Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=139102&r1=139101&r2=139102&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Sun Sep  4 14:54:14 2011
@@ -1313,6 +1313,9 @@
     FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
 
     if (ForRangeInit.ParsedForRangeDecl()) {
+      if (!getLang().CPlusPlus0x)
+        Diag(ForRangeInit.ColonLoc, diag::ext_for_range);
+
       ForRange = true;
     } else if (Tok.is(tok::semi)) {  // for (int x = 4;
       ConsumeToken();

Modified: cfe/trunk/lib/Sema/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=139102&r1=139101&r2=139102&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/DeclSpec.cpp (original)
+++ cfe/trunk/lib/Sema/DeclSpec.cpp Sun Sep  4 14:54:14 2011
@@ -425,10 +425,23 @@
   }
 
   if (StorageClassSpec != SCS_unspecified) {
+    // Maybe this is an attempt to use C++0x 'auto' outside of C++0x mode.
+    bool isInvalid = true;
+    if (TypeSpecType == TST_unspecified && Lang.CPlusPlus) {
+      if (S == SCS_auto)
+        return SetTypeSpecType(TST_auto, Loc, PrevSpec, DiagID);
+      if (StorageClassSpec == SCS_auto) {
+        isInvalid = SetTypeSpecType(TST_auto, StorageClassSpecLoc,
+                                    PrevSpec, DiagID);
+        assert(!isInvalid && "auto SCS -> TST recovery failed");
+      }
+    }
+
     // Changing storage class is allowed only if the previous one
     // was the 'extern' that is part of a linkage specification and
     // the new storage class is 'typedef'.
-    if (!(SCS_extern_in_linkage_spec &&
+    if (isInvalid &&
+        !(SCS_extern_in_linkage_spec &&
           StorageClassSpec == SCS_extern &&
           S == SCS_typedef))
       return BadSpecifier(S, (SCS)StorageClassSpec, PrevSpec, DiagID);
@@ -836,6 +849,27 @@
     }
   }
 
+  // If no type specifier was provided and we're parsing a language where
+  // the type specifier is not optional, but we got 'auto' as a storage
+  // class specifier, then assume this is an attempt to use C++0x's 'auto'
+  // type specifier.
+  // FIXME: Does Microsoft really support implicit int in C++?
+  if (PP.getLangOptions().CPlusPlus && !PP.getLangOptions().Microsoft &&
+      TypeSpecType == TST_unspecified && StorageClassSpec == SCS_auto) {
+    TypeSpecType = TST_auto;
+    StorageClassSpec = StorageClassSpecAsWritten = SCS_unspecified;
+    TSTLoc = TSTNameLoc = StorageClassSpecLoc;
+    StorageClassSpecLoc = SourceLocation();
+  }
+  // Diagnose if we've recovered from an ill-formed 'auto' storage class
+  // specifier in a pre-C++0x dialect of C++.
+  if (!PP.getLangOptions().CPlusPlus0x && TypeSpecType == TST_auto)
+    Diag(D, TSTLoc, diag::ext_auto_type_specifier);
+  if (PP.getLangOptions().CPlusPlus && !PP.getLangOptions().CPlusPlus0x &&
+      StorageClassSpec == SCS_auto)
+    Diag(D, StorageClassSpecLoc, diag::warn_auto_storage_class)
+      << FixItHint::CreateRemoval(StorageClassSpecLoc);
+
   // C++ [class.friend]p6:
   //   No storage-class-specifier shall appear in the decl-specifier-seq
   //   of a friend declaration.

Modified: cfe/trunk/test/CXX/class/class.friend/p6.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.friend/p6.cpp?rev=139102&r1=139101&r2=139102&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class/class.friend/p6.cpp (original)
+++ cfe/trunk/test/CXX/class/class.friend/p6.cpp Sun Sep  4 14:54:14 2011
@@ -3,7 +3,7 @@
 class A {
   friend static class B; // expected-error {{'static' is invalid in friend declarations}}
   friend extern class C; // expected-error {{'extern' is invalid in friend declarations}}
-  friend auto class D; // expected-error {{'auto' is invalid in friend declarations}}
+  friend auto class D; // expected-warning {{incompatible with C++0x}} expected-error {{'auto' is invalid in friend declarations}}
   friend register class E; // expected-error {{'register' is invalid in friend declarations}}
   friend mutable class F; // expected-error {{'mutable' is invalid in friend declarations}}
   friend typedef class G; // expected-error {{'typedef' is invalid in friend declarations}}

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp?rev=139102&r1=139101&r2=139102&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp Sun Sep  4 14:54:14 2011
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++0x-extensions
 void f() {
   auto a = a; // expected-error{{variable 'a' declared with 'auto' type cannot appear in its own initializer}}
   auto *b = b; // expected-error{{variable 'b' declared with 'auto' type cannot appear in its own initializer}}
@@ -39,10 +40,12 @@
   auto x = 5;
   const auto *v = &x, u = 6;
   static auto y = 0.0;
-  auto int r; // expected-warning {{'auto' storage class specifier is redundant and will be removed in future releases}}
-
-  same<decltype(x), int> xHasTypeInt;
-  same<decltype(v), const int*> vHasTypeConstIntPtr;
-  same<decltype(u), const int> uHasTypeConstInt;
-  same<decltype(y), double> yHasTypeDouble;
+  // In C++98: 'auto' storage class specifier is redundant and incompatible with C++0x
+  // In C++0x: 'auto' storage class specifier is not permitted in C++0x, and will not be supported in future releases
+  auto int r; // expected-warning {{'auto' storage class specifier}}
+
+  same<__typeof(x), int> xHasTypeInt;
+  same<__typeof(v), const int*> vHasTypeConstIntPtr;
+  same<__typeof(u), const int> uHasTypeConstInt;
+  same<__typeof(y), double> yHasTypeDouble;
 }

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp?rev=139102&r1=139101&r2=139102&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp Sun Sep  4 14:54:14 2011
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++0x-extensions
 
 template<typename T>
 struct only {
@@ -19,7 +20,10 @@
   for (; auto a = false; ) {
   }
 
+  // FIXME: support 'auto' error recovery here in pre-C++0x mode.
+#if __has_feature(cxx_auto_type)
   new const auto (0);
+#endif
   new (auto) (0.0);
 
   int arr[] = {1, 2, 3};

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp?rev=139102&r1=139101&r2=139102&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp Sun Sep  4 14:54:14 2011
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++0x-extensions
 
 template<typename T>
 struct only {

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp?rev=139102&r1=139101&r2=139102&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp Sun Sep  4 14:54:14 2011
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++0x-extensions
 void f() {
   auto a = 0, b = 0, c = 0;
   auto d = 0, e = 0.0; // expected-error {{'int' in declaration of 'd' and deduced as 'double' in declaration of 'e'}}
@@ -18,6 +19,14 @@
 }
 
 void g() {
-  auto a = 0, (*b)() -> void, c = 0;
-  auto d = 0, (*e)() -> void, f = 0.0; // expected-error {{'auto' deduced as 'int' in declaration of 'd' and deduced as 'double' in declaration of 'f'}}
+  auto a = 0,
+#if __has_feature(cxx_trailing_return)
+       (*b)() -> void,
+#endif
+       c = 0;
+  auto d = 0, // expected-error {{'auto' deduced as 'int' in declaration of 'd' and deduced as 'double' in declaration of 'f'}}
+#if __has_feature(cxx_trailing_return)
+       (*e)() -> void,
+#endif
+       f = 0.0;
 }

Modified: cfe/trunk/test/Misc/warning-flags.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/warning-flags.c?rev=139102&r1=139101&r2=139102&view=diff
==============================================================================
--- cfe/trunk/test/Misc/warning-flags.c (original)
+++ cfe/trunk/test/Misc/warning-flags.c Sun Sep  4 14:54:14 2011
@@ -18,12 +18,12 @@
 The list of warnings below should NEVER grow.  It should gradually shrink to 0.
 
 CHECK: Warnings without flags (311):
-CHECK-NEXT:   auto_storage_class
 CHECK-NEXT:   backslash_newline_space
 CHECK-NEXT:   charize_microsoft_ext
 CHECK-NEXT:   ext_anon_param_requires_type_specifier
 CHECK-NEXT:   ext_anonymous_struct_union_qualified
 CHECK-NEXT:   ext_array_init_copy
+CHECK-NEXT:   ext_auto_storage_class
 CHECK-NEXT:   ext_binary_literal
 CHECK-NEXT:   ext_c1x_generic_selection
 CHECK-NEXT:   ext_c1x_static_assert

Added: cfe/trunk/test/SemaCXX/PR10458.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/PR10458.cpp?rev=139102&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/PR10458.cpp (added)
+++ cfe/trunk/test/SemaCXX/PR10458.cpp Sun Sep  4 14:54:14 2011
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98
+
+void f() {
+  int arr[] = { 1, 2, 3 };
+  for (auto &i : arr) { // expected-warning {{'auto' type specifier is a C++0x extension}} expected-warning {{range-based for loop is a C++0x extension}}
+  }
+}

Modified: cfe/trunk/test/SemaCXX/auto-cxx0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/auto-cxx0x.cpp?rev=139102&r1=139101&r2=139102&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/auto-cxx0x.cpp (original)
+++ cfe/trunk/test/SemaCXX/auto-cxx0x.cpp Sun Sep  4 14:54:14 2011
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x
 void f() {
-  auto int a; // expected-warning {{'auto' storage class specifier is redundant and will be removed in future releases}}
+  auto int a; // expected-warning {{'auto' storage class specifier is not permitted in C++0x, and will not be supported in future releases}}
   int auto b; // expected-error{{cannot combine with previous 'int' declaration specifier}}
 }

Modified: cfe/trunk/test/SemaCXX/auto-cxx98.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/auto-cxx98.cpp?rev=139102&r1=139101&r2=139102&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/auto-cxx98.cpp (original)
+++ cfe/trunk/test/SemaCXX/auto-cxx98.cpp Sun Sep  4 14:54:14 2011
@@ -1,5 +1,8 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98
 void f() {
-  auto int a;
-  int auto b;
+  auto int a; // expected-warning {{'auto' storage class specifier is redundant and incompatible with C++0x}}
+  int auto b; // expected-warning {{'auto' storage class specifier is redundant and incompatible with C++0x}}
+  auto c; // expected-warning {{C++0x extension}} expected-error {{requires an initializer}}
+  static auto d = 0; // expected-warning {{C++0x extension}}
+  auto static e = 0; // expected-warning {{C++0x extension}}
 }

Modified: cfe/trunk/test/SemaCXX/class.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/class.cpp?rev=139102&r1=139101&r2=139102&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/class.cpp (original)
+++ cfe/trunk/test/SemaCXX/class.cpp Sun Sep  4 14:54:14 2011
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s 
 class C {
 public:
-  auto int errx; // expected-error {{error: storage class specified for a member declaration}}
+  auto int errx; // expected-error {{error: storage class specified for a member declaration}} expected-warning {{'auto' storage class specifier is redundant}}
   register int erry; // expected-error {{error: storage class specified for a member declaration}}
   extern int errz; // expected-error {{error: storage class specified for a member declaration}}
 





More information about the cfe-commits mailing list