|
@@ -802,16 +802,13 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
|
|
|
Expr *baseObjectExpr,
|
|
|
SourceLocation opLoc) {
|
|
|
// First, build the expression that refers to the base object.
|
|
|
-
|
|
|
- bool baseObjectIsPointer = false;
|
|
|
- Qualifiers baseQuals;
|
|
|
-
|
|
|
+
|
|
|
// Case 1: the base of the indirect field is not a field.
|
|
|
VarDecl *baseVariable = indirectField->getVarDecl();
|
|
|
CXXScopeSpec EmptySS;
|
|
|
if (baseVariable) {
|
|
|
assert(baseVariable->getType()->isRecordType());
|
|
|
-
|
|
|
+
|
|
|
// In principle we could have a member access expression that
|
|
|
// accesses an anonymous struct/union that's a static member of
|
|
|
// the base object's class. However, under the current standard,
|
|
@@ -824,68 +821,37 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
|
|
|
ExprResult result
|
|
|
= BuildDeclarationNameExpr(EmptySS, baseNameInfo, baseVariable);
|
|
|
if (result.isInvalid()) return ExprError();
|
|
|
-
|
|
|
- baseObjectExpr = result.get();
|
|
|
- baseObjectIsPointer = false;
|
|
|
- baseQuals = baseObjectExpr->getType().getQualifiers();
|
|
|
-
|
|
|
- // Case 2: the base of the indirect field is a field and the user
|
|
|
- // wrote a member expression.
|
|
|
- } else if (baseObjectExpr) {
|
|
|
- // The caller provided the base object expression. Determine
|
|
|
- // whether its a pointer and whether it adds any qualifiers to the
|
|
|
- // anonymous struct/union fields we're looking into.
|
|
|
- QualType objectType = baseObjectExpr->getType();
|
|
|
-
|
|
|
- if (const PointerType *ptr = objectType->getAs<PointerType>()) {
|
|
|
- baseObjectIsPointer = true;
|
|
|
- objectType = ptr->getPointeeType();
|
|
|
- } else {
|
|
|
- baseObjectIsPointer = false;
|
|
|
- }
|
|
|
- baseQuals = objectType.getQualifiers();
|
|
|
-
|
|
|
- // Case 3: the base of the indirect field is a field and we should
|
|
|
- // build an implicit member access.
|
|
|
- } else {
|
|
|
- // We've found a member of an anonymous struct/union that is
|
|
|
- // inside a non-anonymous struct/union, so in a well-formed
|
|
|
- // program our base object expression is "this".
|
|
|
- QualType ThisTy = getCurrentThisType();
|
|
|
- if (ThisTy.isNull()) {
|
|
|
- Diag(loc, diag::err_invalid_member_use_in_static_method)
|
|
|
- << indirectField->getDeclName();
|
|
|
- return ExprError();
|
|
|
- }
|
|
|
-
|
|
|
- // Our base object expression is "this".
|
|
|
- CheckCXXThisCapture(loc);
|
|
|
- baseObjectExpr
|
|
|
- = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/ true);
|
|
|
- baseObjectIsPointer = true;
|
|
|
- baseQuals = ThisTy->castAs<PointerType>()->getPointeeType().getQualifiers();
|
|
|
+
|
|
|
+ baseObjectExpr = result.get();
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ assert((baseVariable || baseObjectExpr) &&
|
|
|
+ "referencing anonymous struct/union without a base variable or "
|
|
|
+ "expression");
|
|
|
+
|
|
|
// Build the implicit member references to the field of the
|
|
|
// anonymous struct/union.
|
|
|
Expr *result = baseObjectExpr;
|
|
|
IndirectFieldDecl::chain_iterator
|
|
|
FI = indirectField->chain_begin(), FEnd = indirectField->chain_end();
|
|
|
-
|
|
|
- // Build the first member access in the chain with full information.
|
|
|
+
|
|
|
+ // Case 2: the base of the indirect field is a field and the user
|
|
|
+ // wrote a member expression.
|
|
|
if (!baseVariable) {
|
|
|
FieldDecl *field = cast<FieldDecl>(*FI);
|
|
|
-
|
|
|
+
|
|
|
+ bool baseObjectIsPointer = baseObjectExpr->getType()->isPointerType();
|
|
|
+
|
|
|
// Make a nameInfo that properly uses the anonymous name.
|
|
|
DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
|
|
|
|
|
|
- result = BuildFieldReferenceExpr(result, baseObjectIsPointer,
|
|
|
- SourceLocation(), EmptySS, field,
|
|
|
- foundDecl, memberNameInfo).get();
|
|
|
+ // Build the first member access in the chain with full information.
|
|
|
+ result =
|
|
|
+ BuildFieldReferenceExpr(result, baseObjectIsPointer, SourceLocation(),
|
|
|
+ EmptySS, field, foundDecl, memberNameInfo)
|
|
|
+ .get();
|
|
|
if (!result)
|
|
|
return ExprError();
|
|
|
-
|
|
|
- // FIXME: check qualified member access
|
|
|
}
|
|
|
|
|
|
// In all cases, we should now skip the first declaration in the chain.
|