[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