Basic support for member exprs where the base expr type is dependent.
llvm-svn: 71907
This commit is contained in:
parent
9a017d7fcf
commit
789e2cce54
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -125,3 +125,18 @@ template<typename T> struct For0 {
|
|||
};
|
||||
|
||||
template struct For0<int*>;
|
||||
|
||||
template<typename T> 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}}
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue