[cfe-commits] r124785 - in /cfe/trunk: include/clang/Sema/Sema.h lib/CodeGen/CGCXXABI.cpp lib/CodeGen/CGCXXABI.h lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprConstant.cpp lib/CodeGen/CGExprScalar.cpp lib/CodeGen/CGValue.h lib/CodeGen/CodeGenModule.h lib/CodeGen/ItaniumCXXABI.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp
John McCall
rjmccall at apple.com
Thu Feb 3 00:15:49 PST 2011
Author: rjmccall
Date: Thu Feb 3 02:15:49 2011
New Revision: 124785
URL: http://llvm.org/viewvc/llvm-project?rev=124785&view=rev
Log:
More capturing of 'this': implicit member expressions. Getting that
right for anonymous struct/union members led to me discovering some
seemingly broken code in that area of Sema, which I fixed, partly by
changing the representation of member pointer constants so that
IndirectFieldDecls aren't expanded. This led to assorted cleanups with
member pointers in CodeGen, and while I was doing that I saw some random
other things to clean up.
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/CodeGen/CGCXXABI.cpp
cfe/trunk/lib/CodeGen/CGCXXABI.h
cfe/trunk/lib/CodeGen/CGExpr.cpp
cfe/trunk/lib/CodeGen/CGExprConstant.cpp
cfe/trunk/lib/CodeGen/CGExprScalar.cpp
cfe/trunk/lib/CodeGen/CGValue.h
cfe/trunk/lib/CodeGen/CodeGenModule.h
cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=124785&r1=124784&r2=124785&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Feb 3 02:15:49 2011
@@ -1784,11 +1784,11 @@
const DeclarationNameInfo &NameInfo,
const CXXScopeSpec *SS = 0);
ExprResult
- BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
- const CXXScopeSpec &SS,
- IndirectFieldDecl *IndirectField,
- Expr *BaseObjectExpr = 0,
- SourceLocation OpLoc = SourceLocation());
+ BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
+ SourceLocation nameLoc,
+ IndirectFieldDecl *indirectField,
+ Expr *baseObjectExpr = 0,
+ SourceLocation opLoc = SourceLocation());
ExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs);
@@ -2271,7 +2271,12 @@
//// ActOnCXXThis - Parse 'this' pointer.
- ExprResult ActOnCXXThis(SourceLocation ThisLoc);
+ ExprResult ActOnCXXThis(SourceLocation loc);
+
+ /// tryCaptureCXXThis - Try to capture a 'this' pointer. Returns a
+ /// pointer to an instance method whose 'this' pointer is
+ /// capturable, or null if this is not possible.
+ CXXMethodDecl *tryCaptureCXXThis();
/// ActOnCXXBoolLiteral - Parse {true,false} literals.
ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
Modified: cfe/trunk/lib/CodeGen/CGCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.cpp?rev=124785&r1=124784&r2=124785&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.cpp Thu Feb 3 02:15:49 2011
@@ -105,10 +105,9 @@
MD->getParent()->getTypeForDecl()));
}
-llvm::Constant *CGCXXABI::EmitMemberPointer(const FieldDecl *FD) {
- return GetBogusMemberPointer(CGM,
- CGM.getContext().getMemberPointerType(FD->getType(),
- FD->getParent()->getTypeForDecl()));
+llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
+ CharUnits offset) {
+ return GetBogusMemberPointer(CGM, QualType(MPT, 0));
}
bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=124785&r1=124784&r2=124785&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Thu Feb 3 02:15:49 2011
@@ -122,7 +122,8 @@
virtual llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
/// Create a member pointer for the given field.
- virtual llvm::Constant *EmitMemberPointer(const FieldDecl *FD);
+ virtual llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
+ CharUnits offset);
/// Emit a comparison between two member pointers. Returns an i1.
virtual llvm::Value *
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=124785&r1=124784&r2=124785&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Feb 3 02:15:49 2011
@@ -1178,24 +1178,10 @@
setObjCGCLValueClass(getContext(), E, LV);
return LV;
}
-
- // If we're emitting an instance method as an independent lvalue,
- // we're actually emitting a member pointer.
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))
- if (MD->isInstance()) {
- llvm::Value *V = CGM.getCXXABI().EmitMemberPointer(MD);
- return MakeAddrLValue(V, MD->getType(), Alignment);
- }
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
- return EmitFunctionDeclLValue(*this, E, FD);
-
- // If we're emitting a field as an independent lvalue, we're
- // actually emitting a member pointer.
- if (const FieldDecl *FD = dyn_cast<FieldDecl>(ND)) {
- llvm::Value *V = CGM.getCXXABI().EmitMemberPointer(FD);
- return MakeAddrLValue(V, FD->getType(), Alignment);
- }
-
+
+ if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(ND))
+ return EmitFunctionDeclLValue(*this, E, fn);
+
assert(false && "Unhandled DeclRefExpr");
// an invalid LValue, but the assert will
Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=124785&r1=124784&r2=124785&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Thu Feb 3 02:15:49 2011
@@ -450,17 +450,10 @@
llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
return Visit(E->getInitializer());
}
-
+
llvm::Constant *VisitUnaryAddrOf(UnaryOperator *E) {
- if (const MemberPointerType *MPT =
- E->getType()->getAs<MemberPointerType>()) {
- DeclRefExpr *DRE = cast<DeclRefExpr>(E->getSubExpr());
- NamedDecl *ND = DRE->getDecl();
- if (MPT->isMemberFunctionPointer())
- return CGM.getCXXABI().EmitMemberPointer(cast<CXXMethodDecl>(ND));
- else
- return CGM.getCXXABI().EmitMemberPointer(cast<FieldDecl>(ND));
- }
+ if (E->getType()->isMemberPointerType())
+ return CGM.getMemberPointerConstant(E);
return 0;
}
@@ -934,6 +927,38 @@
return C;
}
+static uint64_t getFieldOffset(ASTContext &C, const FieldDecl *field) {
+ const ASTRecordLayout &layout = C.getASTRecordLayout(field->getParent());
+ return layout.getFieldOffset(field->getFieldIndex());
+}
+
+llvm::Constant *
+CodeGenModule::getMemberPointerConstant(const UnaryOperator *uo) {
+ // Member pointer constants always have a very particular form.
+ const MemberPointerType *type = cast<MemberPointerType>(uo->getType());
+ const ValueDecl *decl = cast<DeclRefExpr>(uo->getSubExpr())->getDecl();
+
+ // A member function pointer.
+ if (const CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(decl))
+ return getCXXABI().EmitMemberPointer(method);
+
+ // Otherwise, a member data pointer.
+ uint64_t fieldOffset;
+ if (const FieldDecl *field = dyn_cast<FieldDecl>(decl))
+ fieldOffset = getFieldOffset(getContext(), field);
+ else {
+ const IndirectFieldDecl *ifield = cast<IndirectFieldDecl>(decl);
+
+ fieldOffset = 0;
+ for (IndirectFieldDecl::chain_iterator ci = ifield->chain_begin(),
+ ce = ifield->chain_end(); ci != ce; ++ci)
+ fieldOffset += getFieldOffset(getContext(), cast<FieldDecl>(*ci));
+ }
+
+ CharUnits chars = getContext().toCharUnitsFromBits((int64_t) fieldOffset);
+ return getCXXABI().EmitMemberDataPointer(type, chars);
+}
+
static void
FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T,
std::vector<llvm::Constant *> &Elements,
@@ -1000,9 +1025,10 @@
uint64_t StartIndex = StartOffset / 8;
uint64_t EndIndex = StartIndex + CGM.getContext().getTypeSize(T) / 8;
+ // FIXME: hardcodes Itanium member pointer representation!
llvm::Constant *NegativeOne =
llvm::ConstantInt::get(llvm::Type::getInt8Ty(CGM.getLLVMContext()),
- -1ULL, /*isSigned=*/true);
+ -1ULL, /*isSigned*/true);
// Fill in the null data member pointer.
for (uint64_t I = StartIndex; I != EndIndex; ++I)
@@ -1123,6 +1149,5 @@
// Itanium C++ ABI 2.3:
// A NULL pointer is represented as -1.
- return llvm::ConstantInt::get(getTypes().ConvertTypeForMem(T), -1ULL,
- /*isSigned=*/true);
+ return getCXXABI().EmitNullMemberPointer(T->castAs<MemberPointerType>());
}
Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=124785&r1=124784&r2=124785&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Thu Feb 3 02:15:49 2011
@@ -307,9 +307,9 @@
Value *VisitUnaryAddrOf(const UnaryOperator *E) {
- // If the sub-expression is an instance member reference,
- // EmitDeclRefLValue will magically emit it with the appropriate
- // value as the "address".
+ if (isa<MemberPointerType>(E->getType())) // never sugared
+ return CGF.CGM.getMemberPointerConstant(E);
+
return EmitLValue(E->getSubExpr()).getAddress();
}
Value *VisitUnaryDeref(const UnaryOperator *E) {
Modified: cfe/trunk/lib/CodeGen/CGValue.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGValue.h?rev=124785&r1=124784&r2=124785&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGValue.h (original)
+++ cfe/trunk/lib/CodeGen/CGValue.h Thu Feb 3 02:15:49 2011
@@ -254,7 +254,7 @@
static LValue MakeAddr(llvm::Value *V, QualType T, unsigned Alignment,
ASTContext &Context,
llvm::MDNode *TBAAInfo = 0) {
- Qualifiers Quals = Context.getCanonicalType(T).getQualifiers();
+ Qualifiers Quals = T.getQualifiers();
Quals.setObjCGCAttr(Context.getObjCGCAttrKind(T));
LValue R;
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=124785&r1=124784&r2=124785&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Thu Feb 3 02:15:49 2011
@@ -438,6 +438,8 @@
Types.UpdateCompletedType(TD);
}
+ llvm::Constant *getMemberPointerConstant(const UnaryOperator *e);
+
/// EmitConstantExpr - Try to emit the given expression as a
/// constant; returns 0 if the expression cannot be emitted as a
/// constant.
Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=124785&r1=124784&r2=124785&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Thu Feb 3 02:15:49 2011
@@ -79,7 +79,8 @@
llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
- llvm::Constant *EmitMemberPointer(const FieldDecl *FD);
+ llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
+ CharUnits offset);
llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF,
llvm::Value *L,
@@ -493,43 +494,13 @@
/*Packed=*/false);
}
-static uint64_t getFieldOffset(const FieldDecl *FD, CodeGenModule &CGM) {
- const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(FD->getParent());
- const llvm::StructType *ClassLTy = RL.getLLVMType();
-
- unsigned FieldNo = RL.getLLVMFieldNo(FD);
- return
- CGM.getTargetData().getStructLayout(ClassLTy)->getElementOffset(FieldNo);
-}
-
-llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const FieldDecl *FD) {
+llvm::Constant *
+ItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
+ CharUnits offset) {
// Itanium C++ ABI 2.3:
// A pointer to data member is an offset from the base address of
// the class object containing it, represented as a ptrdiff_t
-
- const RecordDecl *parent = FD->getParent();
- if (!parent->isAnonymousStructOrUnion())
- return llvm::ConstantInt::get(getPtrDiffTy(), getFieldOffset(FD, CGM));
-
- // Handle a field injected from an anonymous struct or union.
-
- assert(FD->getDeclName() && "Requested pointer to member with no name!");
-
- // Find the record which the field was injected into.
- while (parent->isAnonymousStructOrUnion())
- parent = cast<RecordDecl>(parent->getParent());
-
- RecordDecl::lookup_const_result lookup = parent->lookup(FD->getDeclName());
- assert(lookup.first != lookup.second && "Didn't find the field!");
- const IndirectFieldDecl *indirectFD = cast<IndirectFieldDecl>(*lookup.first);
-
- uint64_t Offset = 0;
- for (IndirectFieldDecl::chain_iterator
- I= indirectFD->chain_begin(), E= indirectFD->chain_end(); I!=E; ++I) {
- Offset += getFieldOffset(cast<FieldDecl>(*I), CGM);
- }
-
- return llvm::ConstantInt::get(getPtrDiffTy(), Offset);
+ return llvm::ConstantInt::get(getPtrDiffTy(), offset.getQuantity());
}
llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=124785&r1=124784&r2=124785&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Feb 3 02:15:49 2011
@@ -889,109 +889,116 @@
const DeclarationNameInfo &MemberNameInfo);
ExprResult
-Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
- const CXXScopeSpec &SS,
- IndirectFieldDecl *IndirectField,
- Expr *BaseObjectExpr,
- SourceLocation OpLoc) {
- // Build the expression that refers to the base object, from
- // which we will build a sequence of member references to each
- // of the anonymous union objects and, eventually, the field we
- // found via name lookup.
- bool BaseObjectIsPointer = false;
- Qualifiers BaseQuals;
- VarDecl *BaseObject = IndirectField->getVarDecl();
- if (BaseObject) {
- // BaseObject is an anonymous struct/union variable (and is,
- // therefore, not part of another non-anonymous record).
- MarkDeclarationReferenced(Loc, BaseObject);
- BaseObjectExpr =
- new (Context) DeclRefExpr(BaseObject, BaseObject->getType(),
- VK_LValue, Loc);
- BaseQuals
- = Context.getCanonicalType(BaseObject->getType()).getQualifiers();
- } else if (BaseObjectExpr) {
+Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
+ SourceLocation loc,
+ IndirectFieldDecl *indirectField,
+ 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();
+ 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,
+ // static data members cannot be anonymous structs or unions.
+ // Supporting this is as easy as building a MemberExpr here.
+ assert(!baseObjectExpr && "anonymous struct/union is static data member?");
+
+ DeclarationNameInfo baseNameInfo(DeclarationName(), loc);
+
+ ExprResult result =
+ BuildDeclarationNameExpr(SS, baseNameInfo, baseVariable);
+ if (result.isInvalid()) return ExprError();
+
+ baseObjectExpr = result.take();
+ 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 *ObjectPtr = ObjectType->getAs<PointerType>()) {
- BaseObjectIsPointer = true;
- ObjectType = ObjectPtr->getPointeeType();
+ QualType objectType = baseObjectExpr->getType();
+
+ if (const PointerType *ptr = objectType->getAs<PointerType>()) {
+ baseObjectIsPointer = true;
+ objectType = ptr->getPointeeType();
+ } else {
+ baseObjectIsPointer = false;
}
- BaseQuals
- = Context.getCanonicalType(ObjectType).getQualifiers();
+ 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".
- DeclContext *DC = getFunctionLevelDeclContext();
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) {
- if (!MD->isStatic()) {
- QualType AnonFieldType
- = Context.getTagDeclType(
- cast<RecordDecl>(
- (*IndirectField->chain_begin())->getDeclContext()));
- QualType ThisType = Context.getTagDeclType(MD->getParent());
- if ((Context.getCanonicalType(AnonFieldType)
- == Context.getCanonicalType(ThisType)) ||
- IsDerivedFrom(ThisType, AnonFieldType)) {
- // Our base object expression is "this".
- BaseObjectExpr = new (Context) CXXThisExpr(Loc,
- MD->getThisType(Context),
- /*isImplicit=*/true);
- BaseObjectIsPointer = true;
- }
- } else {
- return ExprError(Diag(Loc,diag::err_invalid_member_use_in_static_method)
- << IndirectField->getDeclName());
- }
- BaseQuals = Qualifiers::fromCVRMask(MD->getTypeQualifiers());
+ CXXMethodDecl *method = tryCaptureCXXThis();
+ if (!method) {
+ Diag(loc, diag::err_invalid_member_use_in_static_method)
+ << indirectField->getDeclName();
+ return ExprError();
}
- if (!BaseObjectExpr) {
- // The field is referenced for a pointer-to-member expression, e.g:
- //
- // struct S {
- // union {
- // char c;
- // };
- // };
- // char S::*foo = &S::c;
- //
- FieldDecl *field = IndirectField->getAnonField();
- DeclarationNameInfo NameInfo(field->getDeclName(), Loc);
- return BuildDeclRefExpr(field, field->getType().getNonReferenceType(),
- VK_LValue, NameInfo, &SS);
- }
+ // Our base object expression is "this".
+ baseObjectExpr =
+ new (Context) CXXThisExpr(loc, method->getThisType(Context),
+ /*isImplicit=*/ true);
+ baseObjectIsPointer = true;
+ baseQuals = Qualifiers::fromCVRMask(method->getTypeQualifiers());
}
// Build the implicit member references to the field of the
// anonymous struct/union.
- Expr *Result = BaseObjectExpr;
+ Expr *result = baseObjectExpr;
+ IndirectFieldDecl::chain_iterator
+ FI = indirectField->chain_begin(), FEnd = indirectField->chain_end();
- IndirectFieldDecl::chain_iterator FI = IndirectField->chain_begin(),
- FEnd = IndirectField->chain_end();
+ // Build the first member access in the chain with full information.
+ if (!baseVariable) {
+ FieldDecl *field = cast<FieldDecl>(*FI);
+
+ // FIXME: use the real found-decl info!
+ DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess());
+
+ // Make a nameInfo that properly uses the anonymous name.
+ DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
+
+ result = BuildFieldReferenceExpr(*this, result, baseObjectIsPointer,
+ SS, field, foundDecl,
+ memberNameInfo).take();
+ baseObjectIsPointer = false;
+
+ // FIXME: check qualified member access
+ }
+
+ // In all cases, we should now skip the first declaration in the chain.
+ ++FI;
- // Skip the first VarDecl if present.
- if (BaseObject)
- FI++;
for (; FI != FEnd; FI++) {
- FieldDecl *Field = cast<FieldDecl>(*FI);
+ FieldDecl *field = cast<FieldDecl>(*FI);
// FIXME: these are somewhat meaningless
- DeclarationNameInfo MemberNameInfo(Field->getDeclName(), Loc);
- DeclAccessPair FoundDecl = DeclAccessPair::make(Field, Field->getAccess());
+ DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
+ DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess());
+ CXXScopeSpec memberSS;
- Result = BuildFieldReferenceExpr(*this, Result, BaseObjectIsPointer,
- SS, Field, FoundDecl, MemberNameInfo)
+ result = BuildFieldReferenceExpr(*this, result, /*isarrow*/ false,
+ memberSS, field, foundDecl, memberNameInfo)
.take();
-
- // All the implicit accesses are dot-accesses.
- BaseObjectIsPointer = false;
}
- return Owned(Result);
+ return Owned(result);
}
/// Decomposes the given name into a DeclarationNameInfo, its location, and
@@ -1186,23 +1193,24 @@
/// Diagnose a reference to a field with no object available.
static void DiagnoseInstanceReference(Sema &SemaRef,
const CXXScopeSpec &SS,
- const LookupResult &R) {
- SourceLocation Loc = R.getNameLoc();
+ NamedDecl *rep,
+ const DeclarationNameInfo &nameInfo) {
+ SourceLocation Loc = nameInfo.getLoc();
SourceRange Range(Loc);
if (SS.isSet()) Range.setBegin(SS.getRange().getBegin());
- if (R.getAsSingle<FieldDecl>() || R.getAsSingle<IndirectFieldDecl>()) {
+ if (isa<FieldDecl>(rep) || isa<IndirectFieldDecl>(rep)) {
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(SemaRef.CurContext)) {
if (MD->isStatic()) {
// "invalid use of member 'x' in static member function"
SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method)
- << Range << R.getLookupName();
+ << Range << nameInfo.getName();
return;
}
}
SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use)
- << R.getLookupName() << Range;
+ << nameInfo.getName() << Range;
return;
}
@@ -1678,7 +1686,8 @@
case IMA_Error_StaticContext:
case IMA_Error_Unrelated:
- DiagnoseInstanceReference(*this, SS, R);
+ DiagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(),
+ R.getLookupNameInfo());
return ExprError();
}
@@ -2075,29 +2084,30 @@
bool IsKnownInstance) {
assert(!R.empty() && !R.isAmbiguous());
- SourceLocation Loc = R.getNameLoc();
+ SourceLocation loc = R.getNameLoc();
// We may have found a field within an anonymous union or struct
// (C++ [class.union]).
- // FIXME: This needs to happen post-isImplicitMemberReference?
// FIXME: template-ids inside anonymous structs?
if (IndirectFieldDecl *FD = R.getAsSingle<IndirectFieldDecl>())
- return BuildAnonymousStructUnionMemberReference(Loc, SS, FD);
+ return BuildAnonymousStructUnionMemberReference(SS, R.getNameLoc(), FD);
-
- // If this is known to be an instance access, go ahead and build a
+ // If this is known to be an instance access, go ahead and build an
+ // implicit 'this' expression now.
// 'this' expression now.
- DeclContext *DC = getFunctionLevelDeclContext();
- QualType ThisType = cast<CXXMethodDecl>(DC)->getThisType(Context);
- Expr *This = 0; // null signifies implicit access
+ CXXMethodDecl *method = tryCaptureCXXThis();
+ assert(method && "didn't correctly pre-flight capture of 'this'");
+
+ QualType thisType = method->getThisType(Context);
+ Expr *baseExpr = 0; // null signifies implicit access
if (IsKnownInstance) {
SourceLocation Loc = R.getNameLoc();
if (SS.getRange().isValid())
Loc = SS.getRange().getBegin();
- This = new (Context) CXXThisExpr(Loc, ThisType, /*isImplicit=*/true);
+ baseExpr = new (Context) CXXThisExpr(loc, thisType, /*isImplicit=*/true);
}
- return BuildMemberReferenceExpr(This, ThisType,
+ return BuildMemberReferenceExpr(baseExpr, thisType,
/*OpLoc*/ SourceLocation(),
/*IsArrow*/ true,
SS,
@@ -2221,6 +2231,7 @@
// FIXME: It's not clear to me why NonTypeTemplateParmDecl is a VarDecl.
if (isa<VarDecl>(D) && !isa<NonTypeTemplateParmDecl>(D)) return VK_LValue;
if (isa<FieldDecl>(D)) return VK_LValue;
+ if (isa<IndirectFieldDecl>(D)) return VK_LValue;
if (!Context.getLangOptions().CPlusPlus) return VK_RValue;
if (isa<FunctionDecl>(D)) {
if (isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance())
@@ -2273,9 +2284,13 @@
if (VD->isInvalidDecl())
return ExprError();
- // Handle anonymous.
- if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(VD))
- return BuildAnonymousStructUnionMemberReference(Loc, SS, FD);
+ // Handle members of anonymous structs and unions. If we got here,
+ // and the reference is to a class member indirect field, then this
+ // must be the subject of a pointer-to-member expression.
+ if (IndirectFieldDecl *indirectField = dyn_cast<IndirectFieldDecl>(VD))
+ if (!indirectField->isCXXClassMember())
+ return BuildAnonymousStructUnionMemberReference(SS, NameInfo.getLoc(),
+ indirectField);
ExprValueKind VK = getValueKindForDecl(Context, VD);
@@ -3161,14 +3176,15 @@
Expr *BaseExpr,
QualType BaseType,
const CXXScopeSpec &SS,
- const LookupResult &R) {
+ NamedDecl *rep,
+ const DeclarationNameInfo &nameInfo) {
// If this is an implicit member access, use a different set of
// diagnostics.
if (!BaseExpr)
- return DiagnoseInstanceReference(SemaRef, SS, R);
+ return DiagnoseInstanceReference(SemaRef, SS, rep, nameInfo);
- SemaRef.Diag(R.getNameLoc(), diag::err_qualified_member_of_unrelated)
- << SS.getRange() << R.getRepresentativeDecl() << BaseType;
+ SemaRef.Diag(nameInfo.getLoc(), diag::err_qualified_member_of_unrelated)
+ << SS.getRange() << rep << BaseType;
}
// Check whether the declarations we found through a nested-name
@@ -3217,7 +3233,9 @@
return false;
}
- DiagnoseQualifiedMemberReference(*this, BaseExpr, BaseType, SS, R);
+ DiagnoseQualifiedMemberReference(*this, BaseExpr, BaseType, SS,
+ R.getRepresentativeDecl(),
+ R.getLookupNameInfo());
return true;
}
@@ -3455,7 +3473,7 @@
if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl))
// We may have found a field within an anonymous union or struct
// (C++ [class.union]).
- return BuildAnonymousStructUnionMemberReference(MemberLoc, SS, FD,
+ return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD,
BaseExpr, OpLoc);
if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
@@ -7255,7 +7273,7 @@
/// - *(x + 1) -> x, if x is an array
/// - &"123"[2] -> 0
/// - & __real__ x -> x
-static NamedDecl *getPrimaryDecl(Expr *E) {
+static ValueDecl *getPrimaryDecl(Expr *E) {
switch (E->getStmtClass()) {
case Stmt::DeclRefExprClass:
return cast<DeclRefExpr>(E)->getDecl();
@@ -7332,7 +7350,7 @@
// Technically, there should be a check for array subscript
// expressions here, but the result of one is always an lvalue anyway.
}
- NamedDecl *dcl = getPrimaryDecl(op);
+ ValueDecl *dcl = getPrimaryDecl(op);
Expr::LValueClassification lval = op->ClassifyLValue(S.Context);
if (lval == Expr::LV_ClassTemporary) {
@@ -7408,17 +7426,17 @@
}
} else if (isa<FunctionTemplateDecl>(dcl)) {
return S.Context.OverloadTy;
- } else if (FieldDecl *FD = dyn_cast<FieldDecl>(dcl)) {
+ } else if (isa<FieldDecl>(dcl) || isa<IndirectFieldDecl>(dcl)) {
// Okay: we can take the address of a field.
// Could be a pointer to member, though, if there is an explicit
// scope qualifier for the class.
if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier()) {
DeclContext *Ctx = dcl->getDeclContext();
if (Ctx && Ctx->isRecord()) {
- if (FD->getType()->isReferenceType()) {
+ if (dcl->getType()->isReferenceType()) {
S.Diag(OpLoc,
diag::err_cannot_form_pointer_to_member_of_reference_type)
- << FD->getDeclName() << FD->getType();
+ << dcl->getDeclName() << dcl->getType();
return QualType();
}
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=124785&r1=124784&r2=124785&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Feb 3 02:15:49 2011
@@ -559,19 +559,22 @@
return false;
}
-ExprResult Sema::ActOnCXXThis(SourceLocation ThisLoc) {
- /// C++ 9.3.2: In the body of a non-static member function, the keyword this
- /// is a non-lvalue expression whose value is the address of the object for
- /// which the function is called.
-
- // Ignore block scopes (but nothing else).
+CXXMethodDecl *Sema::tryCaptureCXXThis() {
+ // Ignore block scopes: we can capture through them.
+ // Ignore nested enum scopes: we'll diagnose non-constant expressions
+ // where they're invalid, and other uses are legitimate.
+ // Don't ignore nested class scopes: you can't use 'this' in a local class.
DeclContext *DC = CurContext;
- while (isa<BlockDecl>(DC)) DC = cast<BlockDecl>(DC)->getDeclContext();
+ while (true) {
+ if (isa<BlockDecl>(DC)) DC = cast<BlockDecl>(DC)->getDeclContext();
+ else if (isa<EnumDecl>(DC)) DC = cast<EnumDecl>(DC)->getDeclContext();
+ else break;
+ }
- // If we're not an instance method, error out.
+ // If we're not in an instance method, error out.
CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC);
if (!method || !method->isInstance())
- return ExprError(Diag(ThisLoc, diag::err_invalid_this_use));
+ return 0;
// Mark that we're closing on 'this' in all the block scopes, if applicable.
for (unsigned idx = FunctionScopes.size() - 1;
@@ -579,7 +582,18 @@
--idx)
cast<BlockScopeInfo>(FunctionScopes[idx])->CapturesCXXThis = true;
- return Owned(new (Context) CXXThisExpr(ThisLoc, method->getThisType(Context),
+ return method;
+}
+
+ExprResult Sema::ActOnCXXThis(SourceLocation loc) {
+ /// C++ 9.3.2: In the body of a non-static member function, the keyword this
+ /// is a non-lvalue expression whose value is the address of the object for
+ /// which the function is called.
+
+ CXXMethodDecl *method = tryCaptureCXXThis();
+ if (!method) return Diag(loc, diag::err_invalid_this_use);
+
+ return Owned(new (Context) CXXThisExpr(loc, method->getThisType(Context),
/*isImplicit=*/false));
}
More information about the cfe-commits
mailing list