diff options
author | Anders Carlsson <andersca@mac.com> | 2009-07-08 21:45:58 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-07-08 21:45:58 +0000 |
commit | f9e48bdea6e56404deb0776bf2d0eddedb77dce3 (patch) | |
tree | 593147f63e06a2c51f97b28b84d4f9feb8daa1ad | |
parent | 1bbeec7eca9030f2efa6c690d5edf7b533a87c1f (diff) |
It's not allowed to form member pointers to members that have reference type. Add a test for this and the rest of [dcl.mptr]p3.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@75054 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 12 | ||||
-rw-r--r-- | test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp | 20 |
3 files changed, 33 insertions, 2 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 50a4ff5327..2132a5f2c3 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1432,6 +1432,9 @@ def err_invalid_declarator_in_function : Error< def err_not_tag_in_scope : Error< "%0 does not name a tag member in the specified scope">; +def err_cannot_form_pointer_to_member_of_reference_type : Error< + "cannot form a pointer-to-member to member %0 of reference type %1">; + def warn_value_always_zero : Warning<"%0 is always zero in this context">; def warn_value_always_false : Warning<"%0 is always false in this context">; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 8ede57c59d..df7e5afb17 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -4687,15 +4687,23 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { } else if (isa<OverloadedFunctionDecl>(dcl) || isa<FunctionTemplateDecl>(dcl)) { return Context.OverloadTy; - } else if (isa<FieldDecl>(dcl)) { + } else if (FieldDecl *FD = dyn_cast<FieldDecl>(dcl)) { // Okay: we can take the address of a field. // Could be a pointer to member, though, if there is an explicit // scope qualifier for the class. if (isa<QualifiedDeclRefExpr>(op)) { DeclContext *Ctx = dcl->getDeclContext(); - if (Ctx && Ctx->isRecord()) + if (Ctx && Ctx->isRecord()) { + if (FD->getType()->isReferenceType()) { + Diag(OpLoc, + diag::err_cannot_form_pointer_to_member_of_reference_type) + << FD->getDeclName() << FD->getType(); + return QualType(); + } + return Context.getMemberPointerType(op->getType(), Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr()); + } } } else if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(dcl)) { // Okay: we can take the address of a function. diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp new file mode 100644 index 0000000000..ee3cbeae4e --- /dev/null +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp @@ -0,0 +1,20 @@ +// RUN: clang-cc -fsyntax-only -verify %t +class A { +public: + int& i; + + A(int& i) : i(i) { } + + static int s; +}; + +void f() { + int b; + A a(b); + + int A::*ip = &A::s; // expected-error {{incompatible type initializing 'int *', expected 'int class A::*'}} + a.*&A::s = 10; // expected-error{{right hand operand to .* has non pointer-to-member type 'int *'}} + a.*&A::i = 10; // expected-error{{cannot form a pointer-to-member to member 'i' of reference type 'int &'}} + + void A::*p = 0; // expected-error{{'p' declared as a member pointer to void}} +} |