[cfe-commits] r132833 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaAccess.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaLookup.cpp
Sean Hunt
scshunt at csclub.uwaterloo.ca
Thu Jun 9 20:50:42 PDT 2011
Author: coppro
Date: Thu Jun 9 22:50:41 2011
New Revision: 132833
URL: http://llvm.org/viewvc/llvm-project?rev=132833&view=rev
Log:
Implement caching of default constructors on the resolution table. This
isn't yet used for the less controlled environments of initialization.
Also a few random text fixups.
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaAccess.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaLookup.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=132833&r1=132832&r2=132833&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Jun 9 22:50:41 2011
@@ -1668,6 +1668,7 @@
SourceLocation GnuLabelLoc = SourceLocation());
DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class);
+ CXXConstructorDecl *LookupDefaultConstructor(CXXRecordDecl *Class);
CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
void ArgumentDependentLookup(DeclarationName Name, bool Operator,
@@ -3465,6 +3466,10 @@
const InitializedEntity &Entity,
AccessSpecifier Access,
bool IsCopyBindingRefToTemp = false);
+ AccessResult CheckConstructorAccess(SourceLocation Loc,
+ CXXConstructorDecl *D,
+ AccessSpecifier Access,
+ PartialDiagnostic PD);
AccessResult CheckDestructorAccess(SourceLocation Loc,
CXXDestructorDecl *Dtor,
const PartialDiagnostic &PDiag);
Modified: cfe/trunk/lib/Sema/SemaAccess.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAccess.cpp?rev=132833&r1=132832&r2=132833&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaAccess.cpp (original)
+++ cfe/trunk/lib/Sema/SemaAccess.cpp Thu Jun 9 22:50:41 2011
@@ -1460,30 +1460,48 @@
AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass,
DeclAccessPair::make(Constructor, Access),
QualType());
+ PartialDiagnostic PD(PDiag());
switch (Entity.getKind()) {
default:
- AccessEntity.setDiag(IsCopyBindingRefToTemp
- ? diag::ext_rvalue_to_reference_access_ctor
- : diag::err_access_ctor);
+ PD = PDiag(IsCopyBindingRefToTemp
+ ? diag::ext_rvalue_to_reference_access_ctor
+ : diag::err_access_ctor);
+
break;
case InitializedEntity::EK_Base:
- AccessEntity.setDiag(PDiag(diag::err_access_base_ctor)
- << Entity.isInheritedVirtualBase()
- << Entity.getBaseSpecifier()->getType()
- << getSpecialMember(Constructor));
+ PD = PDiag(diag::err_access_base_ctor);
+ PD << Entity.isInheritedVirtualBase()
+ << Entity.getBaseSpecifier()->getType() << getSpecialMember(Constructor);
break;
case InitializedEntity::EK_Member: {
const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl());
- AccessEntity.setDiag(PDiag(diag::err_access_field_ctor)
- << Field->getType()
- << getSpecialMember(Constructor));
+ PD = PDiag(diag::err_access_field_ctor);
+ PD << Field->getType() << getSpecialMember(Constructor);
break;
}
}
+ return CheckConstructorAccess(UseLoc, Constructor, Access, PD);
+}
+
+/// Checks access to a constructor.
+Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
+ CXXConstructorDecl *Constructor,
+ AccessSpecifier Access,
+ PartialDiagnostic PD) {
+ if (!getLangOptions().AccessControl ||
+ Access == AS_public)
+ return AR_accessible;
+
+ CXXRecordDecl *NamingClass = Constructor->getParent();
+ AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass,
+ DeclAccessPair::make(Constructor, Access),
+ QualType());
+ AccessEntity.setDiag(PD);
+
return CheckAccess(*this, UseLoc, AccessEntity);
}
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=132833&r1=132832&r2=132833&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Jun 9 22:50:41 2011
@@ -3318,7 +3318,7 @@
// FIXME: We should put some diagnostic logic right into this function.
// C++0x [class.ctor]/5
- // A defaulted default constructor for class X is defined as delete if:
+ // A defaulted default constructor for class X is defined as deleted if:
for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(),
BE = RD->bases_end();
@@ -3331,7 +3331,7 @@
assert(BaseDecl && "base isn't a CXXRecordDecl");
// -- any [direct base class] has a type with a destructor that is
- // delete or inaccessible from the defaulted default constructor
+ // deleted or inaccessible from the defaulted default constructor
CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl);
if (BaseDtor->isDeleted())
return true;
@@ -3343,14 +3343,12 @@
// overload resolution as applied to [its] default constructor
// results in an ambiguity or in a function that is deleted or
// inaccessible from the defaulted default constructor
- InitializedEntity BaseEntity =
- InitializedEntity::InitializeBase(Context, BI, 0);
- InitializationKind Kind =
- InitializationKind::CreateDirect(Loc, Loc, Loc);
-
- InitializationSequence InitSeq(*this, BaseEntity, Kind, 0, 0);
+ CXXConstructorDecl *BaseDefault = LookupDefaultConstructor(BaseDecl);
+ if (!BaseDefault || BaseDefault->isDeleted())
+ return true;
- if (InitSeq.Failed())
+ if (CheckConstructorAccess(Loc, BaseDefault, BaseDefault->getAccess(),
+ PDiag()) != AR_accessible)
return true;
}
@@ -3373,14 +3371,12 @@
// overload resolution as applied to [its] default constructor
// results in an ambiguity or in a function that is deleted or
// inaccessible from the defaulted default constructor
- InitializedEntity BaseEntity =
- InitializedEntity::InitializeBase(Context, BI, BI);
- InitializationKind Kind =
- InitializationKind::CreateDirect(Loc, Loc, Loc);
-
- InitializationSequence InitSeq(*this, BaseEntity, Kind, 0, 0);
+ CXXConstructorDecl *BaseDefault = LookupDefaultConstructor(BaseDecl);
+ if (!BaseDefault || BaseDefault->isDeleted())
+ return true;
- if (InitSeq.Failed())
+ if (CheckConstructorAccess(Loc, BaseDefault, BaseDefault->getAccess(),
+ PDiag()) != AR_accessible)
return true;
}
@@ -3448,22 +3444,24 @@
// This is technically non-conformant, but sanity demands it.
continue;
}
+
+ // -- any non-static data member ... has class type M (or array thereof)
+ // and either M has no default constructor or overload resolution as
+ // applied to M's default constructor results in an ambiguity or in a
+ // function that is deleted or inaccessible from the defaulted default
+ // constructor.
+ CXXConstructorDecl *FieldDefault = LookupDefaultConstructor(FieldRecord);
+ if (!FieldDefault || FieldDefault->isDeleted())
+ return true;
+ if (CheckConstructorAccess(Loc, FieldDefault, FieldDefault->getAccess(),
+ PDiag()) != AR_accessible)
+ return true;
} else if (!Union && FieldType.isConstQualified()) {
// -- any non-variant non-static data member of const-qualified type (or
// array thereof) with no brace-or-equal-initializer does not have a
// user-provided default constructor
return true;
}
-
- InitializedEntity MemberEntity =
- InitializedEntity::InitializeMember(*FI, 0);
- InitializationKind Kind =
- InitializationKind::CreateDirect(Loc, Loc, Loc);
-
- InitializationSequence InitSeq(*this, MemberEntity, Kind, 0, 0);
-
- if (InitSeq.Failed())
- return true;
}
if (Union && AllConst)
@@ -3548,7 +3546,7 @@
CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl();
assert(BaseDecl && "base isn't a CXXRecordDecl");
- // -- any [direct base class] of a type with a destructor that is deleted or
+ // -- any [virtual base class] of a type with a destructor that is deleted or
// inaccessible from the defaulted constructor
CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl);
if (BaseDtor->isDeleted())
@@ -5895,28 +5893,6 @@
};
}
-static CXXConstructorDecl *getDefaultConstructorUnsafe(Sema &Self,
- CXXRecordDecl *D) {
- ASTContext &Context = Self.Context;
- QualType ClassType = Context.getTypeDeclType(D);
- DeclarationName ConstructorName
- = Context.DeclarationNames.getCXXConstructorName(
- Context.getCanonicalType(ClassType.getUnqualifiedType()));
-
- DeclContext::lookup_const_iterator Con, ConEnd;
- for (llvm::tie(Con, ConEnd) = D->lookup(ConstructorName);
- Con != ConEnd; ++Con) {
- // FIXME: In C++0x, a constructor template can be a default constructor.
- if (isa<FunctionTemplateDecl>(*Con))
- continue;
-
- CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
- if (Constructor->isDefaultConstructor())
- return Constructor;
- }
- return 0;
-}
-
Sema::ImplicitExceptionSpecification
Sema::ComputeDefaultedDefaultCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
// C++ [except.spec]p14:
@@ -5933,10 +5909,10 @@
if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
- if (BaseClassDecl->needsImplicitDefaultConstructor())
- ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl));
- else if (CXXConstructorDecl *Constructor
- = getDefaultConstructorUnsafe(*this, BaseClassDecl))
+ CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl);
+ // If this is a deleted function, add it anyway. This might be conformant
+ // with the standard. This might not. I'm not sure. It might not matter.
+ if (Constructor)
ExceptSpec.CalledDecl(Constructor);
}
}
@@ -5947,10 +5923,10 @@
B != BEnd; ++B) {
if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
- if (BaseClassDecl->needsImplicitDefaultConstructor())
- ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl));
- else if (CXXConstructorDecl *Constructor
- = getDefaultConstructorUnsafe(*this, BaseClassDecl))
+ CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl);
+ // If this is a deleted function, add it anyway. This might be conformant
+ // with the standard. This might not. I'm not sure. It might not matter.
+ if (Constructor)
ExceptSpec.CalledDecl(Constructor);
}
}
@@ -5961,12 +5937,14 @@
F != FEnd; ++F) {
if (const RecordType *RecordTy
= Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
- CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
- if (FieldClassDecl->needsImplicitDefaultConstructor())
- ExceptSpec.CalledDecl(
- DeclareImplicitDefaultConstructor(FieldClassDecl));
- else if (CXXConstructorDecl *Constructor
- = getDefaultConstructorUnsafe(*this, FieldClassDecl))
+ CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
+ CXXConstructorDecl *Constructor = LookupDefaultConstructor(FieldRecDecl);
+ // If this is a deleted function, add it anyway. This might be conformant
+ // with the standard. This might not. I'm not sure. It might not matter.
+ // In particular, the problem is that this function never gets called. It
+ // might just be ill-formed because this function attempts to refer to
+ // a deleted function here.
+ if (Constructor)
ExceptSpec.CalledDecl(Constructor);
}
}
Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=132833&r1=132832&r2=132833&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Thu Jun 9 22:50:41 2011
@@ -2186,12 +2186,133 @@
return Result;
}
- llvm_unreachable("haven't implemented this for non-destructors yet");
+ // Prepare for overload resolution. Here we construct a synthetic argument
+ // if necessary and make sure that implicit functions are declared.
+ CanQualType CanTy = Context.getCanonicalType(Context.getTagDeclType(D));
+ DeclarationName Name;
+ Expr *Arg = 0;
+ unsigned NumArgs;
+
+ if (SM == CXXDefaultConstructor) {
+ Name = Context.DeclarationNames.getCXXConstructorName(CanTy);
+ NumArgs = 0;
+ if (D->needsImplicitDefaultConstructor())
+ DeclareImplicitDefaultConstructor(D);
+ } else {
+ if (SM == CXXCopyConstructor || SM == CXXMoveConstructor) {
+ Name = Context.DeclarationNames.getCXXConstructorName(CanTy);
+ if (!D->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(D);
+ // TODO: Move constructors
+ } else {
+ Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
+ if (!D->hasDeclaredCopyAssignment())
+ DeclareImplicitCopyAssignment(D);
+ // TODO: Move assignment
+ }
+
+ QualType ArgType = CanTy;
+ if (ConstArg)
+ ArgType.addConst();
+ if (VolatileArg)
+ ArgType.addVolatile();
+
+ // This isn't /really/ specified by the standard, but it's implied
+ // we should be working from an RValue in the case of move to ensure
+ // that we prefer to bind to rvalue references, and an LValue in the
+ // case of copy to ensure we don't bind to rvalue references.
+ // Possibly an XValue is actually correct in the case of move, but
+ // there is no semantic difference for class types in this restricted
+ // case.
+ ExprValueKind VK;
+ if (SM == CXXCopyAssignment || SM == CXXMoveAssignment)
+ VK = VK_LValue;
+ else
+ VK = VK_RValue;
+
+ NumArgs = 1;
+ Arg = new (Context) OpaqueValueExpr(SourceLocation(), ArgType, VK);
+ }
+
+ // Create the object argument
+ QualType ThisTy = CanTy;
+ if (ConstThis)
+ ThisTy.addConst();
+ if (VolatileThis)
+ ThisTy.addVolatile();
+ Expr::Classification ObjectClassification =
+ (new (Context) OpaqueValueExpr(SourceLocation(), ThisTy,
+ RValueThis ? VK_RValue : VK_LValue))->
+ Classify(Context);
+
+ // Now we perform lookup on the name we computed earlier and do overload
+ // resolution. Lookup is only performed directly into the class since there
+ // will always be a (possibly implicit) declaration to shadow any others.
+ OverloadCandidateSet OCS((SourceLocation()));
+ DeclContext::lookup_iterator I, E;
+ Result->setConstParamMatch(false);
+
+ llvm::tie(I, E) = D->lookup(Name);
+ assert((I != E) &&
+ "lookup for a constructor or assignment operator was empty");
+ for ( ; I != E; ++I) {
+ if ((*I)->isInvalidDecl())
+ continue;
+
+ if (CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(*I)) {
+ AddOverloadCandidate(M, DeclAccessPair::make(M, AS_public), &Arg, NumArgs,
+ OCS, true);
+
+ // Here we're looking for a const parameter to speed up creation of
+ // implicit copy methods.
+ if ((SM == CXXCopyAssignment && M->isCopyAssignmentOperator()) ||
+ (SM == CXXCopyConstructor &&
+ cast<CXXConstructorDecl>(M)->isCopyConstructor())) {
+ QualType ArgType = M->getType()->getAs<FunctionProtoType>()->getArgType(0);
+ if (ArgType->getPointeeType().isConstQualified())
+ Result->setConstParamMatch(true);
+ }
+ } else {
+ FunctionTemplateDecl *Tmpl = cast<FunctionTemplateDecl>(*I);
+ AddTemplateOverloadCandidate(Tmpl, DeclAccessPair::make(Tmpl, AS_public),
+ 0, &Arg, NumArgs, OCS, true);
+ }
+ }
+
+ OverloadCandidateSet::iterator Best;
+ switch (OCS.BestViableFunction(*this, SourceLocation(), Best)) {
+ case OR_Success:
+ Result->setMethod(cast<CXXMethodDecl>(Best->Function));
+ Result->setSuccess(true);
+ break;
+
+ case OR_Deleted:
+ Result->setMethod(cast<CXXMethodDecl>(Best->Function));
+ Result->setSuccess(false);
+ break;
+
+ case OR_Ambiguous:
+ case OR_No_Viable_Function:
+ Result->setMethod(0);
+ Result->setSuccess(false);
+ break;
+ }
+
+ return Result;
+}
+
+/// \brief Look up the default constructor for the given class.
+CXXConstructorDecl *Sema::LookupDefaultConstructor(CXXRecordDecl *Class) {
+ SpecialMemberOverloadResult *Result =
+ LookupSpecialMember(Class, CXXDefaultConstructor, false, false, false,
+ false, false);
+
+ return cast_or_null<CXXConstructorDecl>(Result->getMethod());
}
/// \brief Look up the constructors for the given class.
DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {
- // If the copy constructor has not yet been declared, do so now.
+ // If the implicit constructors have not yet been declared, do so now.
if (CanDeclareSpecialMemberFunction(Context, Class)) {
if (Class->needsImplicitDefaultConstructor())
DeclareImplicitDefaultConstructor(Class);
More information about the cfe-commits
mailing list