forked from OSchip/llvm-project
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:
parent
eb103c404b
commit
9dd13ab202
|
@ -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);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// RUN: %clang_cc1 -verify %s
|
||||
// XFAIL: *
|
||||
|
||||
struct S {
|
||||
typedef struct A {} A; // expected-note {{previous definition is here}}
|
||||
|
|
Loading…
Reference in New Issue