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 | 9dd13ab2025877a9c9d77f624f4d68fc5d86d26a (patch) | |
tree | 2e23681faf7c6df82d5bfea246a0af09cb356b7a /clang/lib | |
parent | eb103c404b314034181d08599c8b7896931d303a (diff) | |
download | bcm5719-llvm-9dd13ab2025877a9c9d77f624f4d68fc5d86d26a.tar.gz bcm5719-llvm-9dd13ab2025877a9c9d77f624f4d68fc5d86d26a.zip |
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
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 69e9ff9e9c6..d5ca944c1d9 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/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); |