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)
|
if (getLangOptions().Microsoft)
|
||||||
return;
|
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) {
|
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))
|
if (!isa<CXXRecordDecl>(CurContext))
|
||||||
return;
|
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)
|
Diag(New->getLocation(), diag::err_redefinition)
|
||||||
<< New->getDeclName();
|
<< New->getDeclName();
|
||||||
Diag(Old->getLocation(), diag::note_previous_definition);
|
Diag(Old->getLocation(), diag::note_previous_definition);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// RUN: %clang_cc1 -verify %s
|
// RUN: %clang_cc1 -verify %s
|
||||||
// XFAIL: *
|
|
||||||
|
|
||||||
struct S {
|
struct S {
|
||||||
typedef struct A {} A; // expected-note {{previous definition is here}}
|
typedef struct A {} A; // expected-note {{previous definition is here}}
|
||||||
|
|
Loading…
Reference in New Issue