]> granicus.if.org Git - clang/commitdiff
Allow redefinitions of typedef-names within class scope when the type
authorDouglas Gregor <dgregor@apple.com>
Mon, 11 Jan 2010 21:54:40 +0000 (21:54 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 11 Jan 2010 21:54:40 +0000 (21:54 +0000)
they redefine is a class-name but not a typedef-name, per C++0x
[dcl.typedef]p4. The code in the test was valid C++98 and is valid
C++0x, but an unintended consequence of DR56 made it ill-formed in
C++03 (which we were luck enough to implement). Fixes PR5455.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93188 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDecl.cpp
test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p4.cpp

index 69e9ff9e9c6fd386c337c35b715026e799aa2472..d5ca944c1d957d00ebd6c65dda48dca975f4fbae 100644 (file)
@@ -803,13 +803,38 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) {
   if (getLangOptions().Microsoft)
     return;
 
-  // C++ [dcl.typedef]p2:
-  //   In a given non-class scope, a typedef specifier can be used to
-  //   redefine the name of any type declared in that scope to refer
-  //   to the type to which it already refers.
   if (getLangOptions().CPlusPlus) {
+    // C++ [dcl.typedef]p2:
+    //   In a given non-class scope, a typedef specifier can be used to
+    //   redefine the name of any type declared in that scope to refer
+    //   to the type to which it already refers.
     if (!isa<CXXRecordDecl>(CurContext))
       return;
+
+    // C++0x [dcl.typedef]p4:
+    //   In a given class scope, a typedef specifier can be used to redefine 
+    //   any class-name declared in that scope that is not also a typedef-name
+    //   to refer to the type to which it already refers.
+    //
+    // This wording came in via DR424, which was a correction to the
+    // wording in DR56, which accidentally banned code like:
+    //
+    //   struct S {
+    //     typedef struct A { } A;
+    //   };
+    //
+    // in the C++03 standard. We implement the C++0x semantics, which
+    // allow the above but disallow
+    //
+    //   struct S {
+    //     typedef int I;
+    //     typedef int I;
+    //   };
+    //
+    // since that was the intent of DR56.
+    if (New->getUnderlyingType()->getAs<ElaboratedType>())
+      return;
+
     Diag(New->getLocation(), diag::err_redefinition)
       << New->getDeclName();
     Diag(Old->getLocation(), diag::note_previous_definition);
index 06c6695008e0684fed90ddf020e386190e693a6d..95fb7885f7cd9a5242ae23cff9409885b648aa22 100644 (file)
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -verify %s
-// XFAIL: *
 
 struct S {
   typedef struct A {} A; // expected-note {{previous definition is here}}