diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-01-11 21:54:40 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-01-11 21:54:40 +0000 |
commit | 93dda720a6f5b67ea997c8d98414f90ec362b43c (patch) | |
tree | bdfac001452b44022af36ed3fe0b19831fe7fe3b /lib/Sema/SemaDecl.cpp | |
parent | 97fd83a8d827400afda3c5fba0840c1f10007239 (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93188 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 69e9ff9e9c..d5ca944c1d 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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); |