A few tweaks to the value-kind computation:

- Default argument expressions pick up the value kind of the incoming
   expression, not the value kind of the parameter it initializes.
 - When building a template argument for substitution, A::x is an rvalue
   if x is an instance method.
 - Anonymous struct/union paths pick up value kind the same way that
   normal member accesses do;  extract out a common code path for this.

Enable the value-kind assertion, now that it passes self-host.

llvm-svn: 120055
This commit is contained in:
John McCall 2010-11-23 20:48:44 +00:00
parent ab7be6e43c
commit feb624a435
4 changed files with 91 additions and 74 deletions

View File

@ -577,12 +577,14 @@ class CXXDefaultArgExpr : public Expr {
param->hasUnparsedDefaultArg()
? param->getType().getNonReferenceType()
: param->getDefaultArg()->getType(),
getValueKindForType(param->getType()), OK_Ordinary, false, false),
param->getDefaultArg()->getValueKind(),
param->getDefaultArg()->getObjectKind(), false, false),
Param(param, false), Loc(Loc) { }
CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param,
Expr *SubExpr)
: Expr(SC, SubExpr->getType(), SubExpr->getValueKind(), OK_Ordinary,
: Expr(SC, SubExpr->getType(),
SubExpr->getValueKind(), SubExpr->getObjectKind(),
false, false), Param(param, true), Loc(Loc) {
*reinterpret_cast<Expr **>(this + 1) = SubExpr;
}

View File

@ -64,7 +64,6 @@ Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const {
kind = Cl::CL_Void;
}
#if 0
// Enable this assertion for testing.
switch (kind) {
case Cl::CL_LValue: assert(getValueKind() == VK_LValue); break;
@ -77,7 +76,6 @@ Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const {
case Cl::CL_ClassTemporary:
case Cl::CL_PRValue: assert(getValueKind() == VK_RValue); break;
}
#endif
Cl::ModifiableType modifiable = Cl::CM_Untested;
if (Loc)

View File

@ -795,6 +795,12 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty,
D, NameInfo, Ty, VK));
}
static ExprResult
BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
const CXXScopeSpec &SS, FieldDecl *Field,
DeclAccessPair FoundDecl,
const DeclarationNameInfo &MemberNameInfo);
ExprResult
Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
IndirectFieldDecl *IndirectField,
@ -863,45 +869,29 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
// Build the implicit member references to the field of the
// anonymous struct/union.
Expr *Result = BaseObjectExpr;
Qualifiers ResultQuals = BaseQuals;
IndirectFieldDecl::chain_iterator FI = IndirectField->chain_begin(),
FEnd = IndirectField->chain_end();
// Skip the first VarDecl if present.
if (BaseObject)
FI++;
for (; FI != FEnd; FI++) {
FieldDecl *Field = cast<FieldDecl>(*FI);
QualType MemberType = Field->getType();
Qualifiers MemberTypeQuals =
Context.getCanonicalType(MemberType).getQualifiers();
// CVR attributes from the base are picked up by members,
// except that 'mutable' members don't pick up 'const'.
if (Field->isMutable())
ResultQuals.removeConst();
// FIXME: the first access can be qualified
CXXScopeSpec SS;
// GC attributes are never picked up by members.
ResultQuals.removeObjCGCAttr();
// FIXME: these are somewhat meaningless
DeclarationNameInfo MemberNameInfo(Field->getDeclName(), Loc);
DeclAccessPair FoundDecl = DeclAccessPair::make(Field, Field->getAccess());
// TR 18037 does not allow fields to be declared with address spaces.
assert(!MemberTypeQuals.hasAddressSpace());
Result = BuildFieldReferenceExpr(*this, Result, BaseObjectIsPointer,
SS, Field, FoundDecl, MemberNameInfo)
.take();
Qualifiers NewQuals = ResultQuals + MemberTypeQuals;
if (NewQuals != MemberTypeQuals)
MemberType = Context.getQualifiedType(MemberType, NewQuals);
MarkDeclarationReferenced(Loc, *FI);
PerformObjectMemberConversion(Result, /*FIXME:Qualifier=*/0, *FI, *FI);
// FIXME: Might this end up being a qualified name?
Result = new (Context) MemberExpr(Result, BaseObjectIsPointer,
cast<FieldDecl>(*FI), OpLoc,
MemberType, VK_LValue,
Field->isBitField() ?
OK_BitField : OK_Ordinary);
// All the implicit accesses are dot-accesses.
BaseObjectIsPointer = false;
ResultQuals = NewQuals;
}
return Owned(Result);
@ -1893,6 +1883,64 @@ static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,
TemplateArgs, Ty, VK, OK);
}
static ExprResult
BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
const CXXScopeSpec &SS, FieldDecl *Field,
DeclAccessPair FoundDecl,
const DeclarationNameInfo &MemberNameInfo) {
// x.a is an l-value if 'a' has a reference type. Otherwise:
// x.a is an l-value/x-value/pr-value if the base is (and note
// that *x is always an l-value), except that if the base isn't
// an ordinary object then we must have an rvalue.
ExprValueKind VK = VK_LValue;
ExprObjectKind OK = OK_Ordinary;
if (!IsArrow) {
if (BaseExpr->getObjectKind() == OK_Ordinary)
VK = BaseExpr->getValueKind();
else
VK = VK_RValue;
}
if (VK != VK_RValue && Field->isBitField())
OK = OK_BitField;
// Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
QualType MemberType = Field->getType();
if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) {
MemberType = Ref->getPointeeType();
VK = VK_LValue;
} else {
QualType BaseType = BaseExpr->getType();
if (IsArrow) BaseType = BaseType->getAs<PointerType>()->getPointeeType();
Qualifiers BaseQuals = BaseType.getQualifiers();
// GC attributes are never picked up by members.
BaseQuals.removeObjCGCAttr();
// CVR attributes from the base are picked up by members,
// except that 'mutable' members don't pick up 'const'.
if (Field->isMutable()) BaseQuals.removeConst();
Qualifiers MemberQuals
= S.Context.getCanonicalType(MemberType).getQualifiers();
// TR 18037 does not allow fields to be declared with address spaces.
assert(!MemberQuals.hasAddressSpace());
Qualifiers Combined = BaseQuals + MemberQuals;
if (Combined != MemberQuals)
MemberType = S.Context.getQualifiedType(MemberType, Combined);
}
S.MarkDeclarationReferenced(MemberNameInfo.getLoc(), Field);
if (S.PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(),
FoundDecl, Field))
return ExprError();
return S.Owned(BuildMemberExpr(S.Context, BaseExpr, IsArrow, SS,
Field, FoundDecl, MemberNameInfo,
MemberType, VK, OK));
}
/// Builds an implicit member access expression. The current context
/// is known to be an instance method, and the given unqualified lookup
/// set is known to contain only instance members, at least one of which
@ -3262,48 +3310,9 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
return ExprError();
}
if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) {
// x.a is an l-value if 'a' has a reference type. Otherwise:
// x.a is an l-value/x-value/pr-value if the base is (and note
// that *x is always an l-value), except that if the base isn't
// an ordinary object then we must have an rvalue.
ExprValueKind VK = VK_LValue;
ExprObjectKind OK = OK_Ordinary;
if (!IsArrow) {
if (BaseExpr->getObjectKind() == OK_Ordinary)
VK = BaseExpr->getValueKind();
else
VK = VK_RValue;
}
if (VK != VK_RValue && FD->isBitField())
OK = OK_BitField;
// Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
QualType MemberType = FD->getType();
if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) {
MemberType = Ref->getPointeeType();
VK = VK_LValue;
} else {
Qualifiers BaseQuals = BaseType.getQualifiers();
BaseQuals.removeObjCGCAttr();
if (FD->isMutable()) BaseQuals.removeConst();
Qualifiers MemberQuals
= Context.getCanonicalType(MemberType).getQualifiers();
Qualifiers Combined = BaseQuals + MemberQuals;
if (Combined != MemberQuals)
MemberType = Context.getQualifiedType(MemberType, Combined);
}
MarkDeclarationReferenced(MemberLoc, FD);
if (PerformObjectMemberConversion(BaseExpr, Qualifier, FoundDecl, FD))
return ExprError();
return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
FD, FoundDecl, MemberNameInfo,
MemberType, VK, OK));
}
if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl))
return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow,
SS, FD, FoundDecl, MemberNameInfo);
if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl))
// We may have found a field within an anonymous union or struct

View File

@ -3365,9 +3365,17 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
ClassType.getTypePtr());
CXXScopeSpec SS;
SS.setScopeRep(Qualifier);
// The actual value-ness of this is unimportant, but for
// internal consistency's sake, references to instance methods
// are r-values.
ExprValueKind VK = VK_LValue;
if (isa<CXXMethodDecl>(VD) && cast<CXXMethodDecl>(VD)->isInstance())
VK = VK_RValue;
ExprResult RefExpr = BuildDeclRefExpr(VD,
VD->getType().getNonReferenceType(),
VK_LValue,
VK,
Loc,
&SS);
if (RefExpr.isInvalid())