aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-11-01 22:13:30 +0000
committerDouglas Gregor <dgregor@apple.com>2011-11-01 22:13:30 +0000
commit5d8419c12a1ffaf710fa11fb1091f10f03f2c1dc (patch)
tree791f70d62a7c437a3af9e8bd539ba80a04b5ce3e
parent0b4072f42f4c94c6c396b43ed3db4d1deecef9c3 (diff)
When we run into a constructor or destructor that is defined in the
wrong class, make sure to drop it immediately; we don't want that constructor to be available within the DeclContext. Fixes <rdar://problem/9677163>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143506 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaDecl.cpp16
-rw-r--r--lib/Sema/SemaDeclCXX.cpp4
-rw-r--r--test/SemaCXX/member-class-11.cpp8
3 files changed, 23 insertions, 5 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 6bd0d25f75..806608cf43 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -3233,13 +3233,23 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
// class X {
// void X::f();
// };
- if (CurContext->Equals(DC))
+ if (CurContext->Equals(DC)) {
Diag(D.getIdentifierLoc(), diag::warn_member_extra_qualification)
<< Name << FixItHint::CreateRemoval(D.getCXXScopeSpec().getRange());
- else
+ } else {
Diag(D.getIdentifierLoc(), diag::err_member_qualification)
<< Name << D.getCXXScopeSpec().getRange();
-
+
+ // C++ constructors and destructors with incorrect scopes can break
+ // our AST invariants by having the wrong underlying types. If
+ // that's the case, then drop this declaration entirely.
+ if ((Name.getNameKind() == DeclarationName::CXXConstructorName ||
+ Name.getNameKind() == DeclarationName::CXXDestructorName) &&
+ !Context.hasSameType(Name.getCXXNameType(),
+ Context.getTypeDeclType(cast<CXXRecordDecl>(CurContext))))
+ return 0;
+ }
+
// Pretend that this qualifier was not here.
D.getCXXScopeSpec().clear();
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 60a128165f..61385f9348 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1534,11 +1534,11 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
DeclContext *DC = 0;
if ((DC = computeDeclContext(SS, false)) && DC->Equals(CurContext))
Diag(D.getIdentifierLoc(), diag::warn_member_extra_qualification)
- << Name << FixItHint::CreateRemoval(SS.getRange());
+ << Name << FixItHint::CreateRemoval(SS.getRange());
else
Diag(D.getIdentifierLoc(), diag::err_member_qualification)
<< Name << SS.getRange();
-
+
SS.clear();
}
diff --git a/test/SemaCXX/member-class-11.cpp b/test/SemaCXX/member-class-11.cpp
new file mode 100644
index 0000000000..c230c5305e
--- /dev/null
+++ b/test/SemaCXX/member-class-11.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+struct rdar9677163 {
+ struct Y { ~Y(); };
+ struct Z { ~Z(); };
+ Y::~Y() { } // expected-error{{non-friend class member '~Y' cannot have a qualified name}}
+ ~Z(); // expected-error{{expected the class name after '~' to name the enclosing class}}
+};