From 789e2cce54dce635b671a03b2bba4efcb9130b5f Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Fri, 15 May 2009 23:10:19 +0000 Subject: [PATCH] Basic support for member exprs where the base expr type is dependent. llvm-svn: 71907 --- clang/include/clang/AST/Expr.h | 3 ++- clang/lib/AST/Expr.cpp | 5 +++++ clang/lib/Sema/SemaExpr.cpp | 16 +++++++++++++++- .../test/SemaTemplate/instantiate-function-1.cpp | 15 +++++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 441aae2c7305..eceb93e64a9b 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -1040,7 +1040,8 @@ class MemberExpr : public Expr { public: MemberExpr(Expr *base, bool isarrow, NamedDecl *memberdecl, SourceLocation l, QualType ty) - : Expr(MemberExprClass, ty), + : Expr(MemberExprClass, ty, + base->isTypeDependent(), base->isValueDependent()), Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow) {} /// \brief Build an empty member reference expression. diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 0d38dd2cd12d..9a860033dfd0 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -417,6 +417,11 @@ Stmt *BlockExpr::getBody() { /// warning. bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, SourceRange &R2) const { + // Don't warn if the expr is type dependent. The type could end up + // instantiating to void. + if (isTypeDependent()) + return false; + switch (getStmtClass()) { default: Loc = getExprLoc(); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 0d72a7534e0f..41c868e00558 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2024,7 +2024,10 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, // Get the type being accessed in BaseType. If this is an arrow, the BaseExpr // must have pointer type, and the accessed type is the pointee. if (OpKind == tok::arrow) { - if (const PointerType *PT = BaseType->getAsPointerType()) + if (BaseType->isDependentType()) + return Owned(new (Context) MemberExpr(BaseExpr, true, 0, + MemberLoc, Context.DependentTy)); + else if (const PointerType *PT = BaseType->getAsPointerType()) BaseType = PT->getPointeeType(); else if (getLangOptions().CPlusPlus && BaseType->isRecordType()) return Owned(BuildOverloadedArrowExpr(S, BaseExpr, OpLoc, @@ -2033,6 +2036,17 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, return ExprError(Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) << BaseType << BaseExpr->getSourceRange()); + } else { + // We use isTemplateTypeParmType directly here, instead of simply checking + // whether BaseType is dependent, because we want to report an error for + // + // T *t; + // t.foo; + // + // + if (BaseType->isTemplateTypeParmType()) + return Owned(new (Context) MemberExpr(BaseExpr, false, 0, + MemberLoc, Context.DependentTy)); } // Handle field access to simple records. This also handles access to fields diff --git a/clang/test/SemaTemplate/instantiate-function-1.cpp b/clang/test/SemaTemplate/instantiate-function-1.cpp index dc4859805051..1dfe9e2da6ac 100644 --- a/clang/test/SemaTemplate/instantiate-function-1.cpp +++ b/clang/test/SemaTemplate/instantiate-function-1.cpp @@ -125,3 +125,18 @@ template struct For0 { }; template struct For0; + +template struct Member0 { + void f(T t) { + t; + t.f; + t->f; + + T* tp; + tp.f; // expected-error{{member reference base type 'T *' is not a structure or union}} + tp->f; + + this->f; + this.f; // expected-error{{member reference base type 'struct Member0 *const' is not a structure or union}} + } +};