Allow redefinitions of typedef-names within class scope when the type

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.

llvm-svn: 93188
This commit is contained in:
Douglas Gregor 2010-01-11 21:54:40 +00:00
parent eb103c404b
commit 9dd13ab202
2 changed files with 29 additions and 5 deletions

View 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);

View File

@ -1,5 +1,4 @@
// RUN: %clang_cc1 -verify %s
// XFAIL: *
struct S {
typedef struct A {} A; // expected-note {{previous definition is here}}