summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-01-11 21:54:40 +0000
committerDouglas Gregor <dgregor@apple.com>2010-01-11 21:54:40 +0000
commit9dd13ab2025877a9c9d77f624f4d68fc5d86d26a (patch)
tree2e23681faf7c6df82d5bfea246a0af09cb356b7a /clang/lib
parenteb103c404b314034181d08599c8b7896931d303a (diff)
downloadbcm5719-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.cpp33
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);
OpenPOWER on IntegriCloud