From: Douglas Gregor Date: Wed, 4 Nov 2009 16:49:01 +0000 (+0000) Subject: Store the unresolved class type in MemberPointerType's Class field, X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=87c12c4a4667279dacb3d4a93c64b49148a0ff79;p=clang Store the unresolved class type in MemberPointerType's Class field, from Peter Collingbourne! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86030 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index aef3d29894..d1b7a364d8 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1374,7 +1374,7 @@ QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) { // If the pointee or class type isn't canonical, this won't be a canonical // type either, so fill in the canonical type field. QualType Canonical; - if (!T.isCanonical()) { + if (!T.isCanonical() || !Cls->isCanonicalUnqualified()) { Canonical = getMemberPointerType(getCanonicalType(T),getCanonicalType(Cls)); // Get the new insert position for the node we care about. diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 3e854ca279..d8b532e697 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -291,7 +291,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E) { const FunctionProtoType *FPT = MPT->getPointeeType()->getAs(); const CXXRecordDecl *RD = - cast(cast(MPT->getClass())->getDecl()); + cast(MPT->getClass()->getAs()->getDecl()); const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT), diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 0003b1b0c4..1a8111c551 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -22,6 +22,7 @@ #include "clang/Basic/PartialDiagnostic.h" #include "clang/Parse/DeclSpec.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/ErrorHandling.h" using namespace clang; /// \brief Perform adjustment on the parameter type of a function. @@ -1162,15 +1163,29 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, } // The scope spec must refer to a class, or be dependent. QualType ClsType; - if (isDependentScopeSpecifier(DeclType.Mem.Scope())) { + if (isDependentScopeSpecifier(DeclType.Mem.Scope()) + || dyn_cast_or_null( + computeDeclContext(DeclType.Mem.Scope()))) { NestedNameSpecifier *NNS = (NestedNameSpecifier *)DeclType.Mem.Scope().getScopeRep(); - assert(NNS->getAsType() && "Nested-name-specifier must name a type"); - ClsType = QualType(NNS->getAsType(), 0); - } else if (CXXRecordDecl *RD - = dyn_cast_or_null( - computeDeclContext(DeclType.Mem.Scope()))) { - ClsType = Context.getTagDeclType(RD); + NestedNameSpecifier *NNSPrefix = NNS->getPrefix(); + switch (NNS->getKind()) { + case NestedNameSpecifier::Identifier: + ClsType = Context.getTypenameType(NNSPrefix, NNS->getAsIdentifier()); + break; + + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::Global: + llvm::llvm_unreachable("Nested-name-specifier must name a type"); + break; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + ClsType = QualType(NNS->getAsType(), 0); + if (NNSPrefix) + ClsType = Context.getQualifiedNameType(NNSPrefix, ClsType); + break; + } } else { Diag(DeclType.Mem.Scope().getBeginLoc(), diag::err_illegal_decl_mempointer_in_nonclass) diff --git a/test/CodeGenCXX/ptr-to-datamember.cpp b/test/CodeGenCXX/ptr-to-datamember.cpp index a7b4cc2f7a..ffaef32a13 100644 --- a/test/CodeGenCXX/ptr-to-datamember.cpp +++ b/test/CodeGenCXX/ptr-to-datamember.cpp @@ -32,6 +32,15 @@ public: F Af; }; +template struct TT { + int T::t::*pti; +}; + +struct I { + typedef I t; + int x; +}; + void pr(const F& b) { printf(" %d %f\n", b.iF, b.fF); } @@ -69,9 +78,12 @@ void test_aggr_pdata_1(A* pa) { int main() { A a1; + TT tt; + I i; int A::* pa = &A::Ai; float A::* pf = &A::f; double A::* pd = &A::d; + tt.pti = &I::x; printf("%d %d %d\n", &A::Ai, &A::f, &A::d); printf("%d\n", &A::B::iB); printf("%d\n", &A::B1::iB1); @@ -81,6 +93,7 @@ int main() printf("%d\n", &A::B::V::iV); printf("%d\n", &A::B1::V::iV); printf("%d, %f, %f \n", a1.*pa, a1.*pf, a1.*pd); + printf("%d\n", i.*tt.pti); test_aggr_pdata(a1); test_aggr_pdata_1(&a1); }