diff options
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 745 |
1 files changed, 436 insertions, 309 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index b8977cf..237a869 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -12,15 +12,17 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "Lookup.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/TypeOrdering.h" #include "clang/AST/StmtVisitor.h" +#include "clang/Parse/DeclSpec.h" +#include "clang/Parse/Template.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Lex/Preprocessor.h" -#include "clang/Parse/DeclSpec.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" #include <algorithm> // for std::equal @@ -264,9 +266,18 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { ParmVarDecl *NewParam = New->getParamDecl(p); if (OldParam->hasDefaultArg() && NewParam->hasDefaultArg()) { + // FIXME: If the parameter doesn't have an identifier then the location + // points to the '=' which means that the fixit hint won't remove any + // extra spaces between the type and the '='. + SourceLocation Begin = NewParam->getLocation(); + if (NewParam->getIdentifier()) + Begin = PP.getLocForEndOfToken(Begin); + Diag(NewParam->getLocation(), diag::err_param_default_argument_redefinition) - << NewParam->getDefaultArgRange(); + << NewParam->getDefaultArgRange() + << CodeModificationHint::CreateRemoval(SourceRange(Begin, + NewParam->getLocEnd())); // Look for the function declaration where the default argument was // actually written, which may be a declaration prior to Old. @@ -577,7 +588,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, for (unsigned idx = 0; idx < NumBases; ++idx) { QualType NewBaseType = Context.getCanonicalType(Bases[idx]->getType()); - NewBaseType = NewBaseType.getUnqualifiedType(); + NewBaseType = NewBaseType.getLocalUnqualifiedType(); if (KnownBaseTypes[NewBaseType]) { // C++ [class.mi]p3: @@ -688,6 +699,8 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, (void)DerivationOkay; if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) { + if (InaccessibleBaseID == 0) + return false; // Check that the base class can be accessed. return CheckBaseClassAccess(Derived, Base, InaccessibleBaseID, Paths, Loc, Name); @@ -718,9 +731,11 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, bool Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, - SourceLocation Loc, SourceRange Range) { + SourceLocation Loc, SourceRange Range, + bool IgnoreAccess) { return CheckDerivedToBaseConversion(Derived, Base, - diag::err_conv_to_inaccessible_base, + IgnoreAccess ? 0 : + diag::err_conv_to_inaccessible_base, diag::err_ambiguous_derived_to_base_conv, Loc, Range, DeclarationName()); } @@ -1018,6 +1033,10 @@ Sema::MemInitResult Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs, SourceLocation IdLoc, SourceLocation RParenLoc) { + // FIXME: CXXBaseOrMemberInitializer should only contain a single + // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary. + ExprTemporaries.clear(); + // Diagnose value-uses of fields to initialize themselves, e.g. // foo(foo) // where foo is not also a parameter to the constructor. @@ -1088,6 +1107,11 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args, return true; Args[0] = NewExp; } + + // FIXME: CXXBaseOrMemberInitializer should only contain a single + // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary. + ExprTemporaries.clear(); + // FIXME: Perform direct initialization of the member. return new (Context) CXXBaseOrMemberInitializer(Member, (Expr **)Args, NumArgs, C, IdLoc, RParenLoc); @@ -1117,8 +1141,7 @@ Sema::BuildBaseInitializer(QualType BaseType, Expr **Args, const CXXBaseSpecifier *DirectBaseSpec = 0; for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); Base != ClassDecl->bases_end(); ++Base) { - if (Context.getCanonicalType(BaseType).getUnqualifiedType() == - Context.getCanonicalType(Base->getType()).getUnqualifiedType()) { + if (Context.hasSameUnqualifiedType(BaseType, Base->getType())) { // We found a direct base of this type. That's what we're // initializing. DirectBaseSpec = &*Base; @@ -1166,7 +1189,7 @@ Sema::BuildBaseInitializer(QualType BaseType, Expr **Args, CXXConstructorDecl *C = 0; if (!BaseType->isDependentType() && !HasDependentArg) { DeclarationName Name = Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(BaseType)); + Context.getCanonicalType(BaseType).getUnqualifiedType()); ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); C = PerformInitializationByConstructor(BaseType, @@ -1182,22 +1205,26 @@ Sema::BuildBaseInitializer(QualType BaseType, Expr **Args, } } + // FIXME: CXXBaseOrMemberInitializer should only contain a single + // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary. + ExprTemporaries.clear(); + return new (Context) CXXBaseOrMemberInitializer(BaseType, (Expr **)Args, NumArgs, C, IdLoc, RParenLoc); } -void +bool Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, CXXBaseOrMemberInitializer **Initializers, unsigned NumInitializers, - llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases, - llvm::SmallVectorImpl<FieldDecl *>&Fields) { + bool IsImplicitConstructor) { // We need to build the initializer AST according to order of construction // and not what user specified in the Initializers list. CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Constructor->getDeclContext()); llvm::SmallVector<CXXBaseOrMemberInitializer*, 32> AllToInit; llvm::DenseMap<const void *, CXXBaseOrMemberInitializer*> AllBaseFields; bool HasDependentBaseInit = false; + bool HadError = false; for (unsigned i = 0; i < NumInitializers; i++) { CXXBaseOrMemberInitializer *Member = Initializers[i]; @@ -1239,13 +1266,8 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, E = ClassDecl->vbases_end(); VBase != E; ++VBase) { if (VBase->getType()->isDependentType()) continue; - if (CXXBaseOrMemberInitializer *Value = - AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) { - CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl()); - assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null"); - if (CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context)) - MarkDeclarationReferenced(Value->getSourceLocation(), Ctor); + if (CXXBaseOrMemberInitializer *Value + = AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) { AllToInit.push_back(Value); } else { @@ -1254,7 +1276,12 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, assert(VBaseDecl && "SetBaseOrMemberInitializers - VBaseDecl null"); CXXConstructorDecl *Ctor = VBaseDecl->getDefaultConstructor(Context); if (!Ctor) { - Bases.push_back(VBase); + Diag(Constructor->getLocation(), diag::err_missing_default_ctor) + << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) + << 0 << VBase->getType(); + Diag(VBaseDecl->getLocation(), diag::note_previous_class_decl) + << Context.getTagDeclType(VBaseDecl); + HadError = true; continue; } @@ -1265,6 +1292,9 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, MarkDeclarationReferenced(Constructor->getLocation(), Ctor); + // FIXME: CXXBaseOrMemberInitializer should only contain a single + // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary. + ExprTemporaries.clear(); CXXBaseOrMemberInitializer *Member = new (Context) CXXBaseOrMemberInitializer(VBase->getType(), CtorArgs.takeAs<Expr>(), @@ -1284,13 +1314,8 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, // Skip dependent types. if (Base->getType()->isDependentType()) continue; - if (CXXBaseOrMemberInitializer *Value = - AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) { - CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null"); - if (CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context)) - MarkDeclarationReferenced(Value->getSourceLocation(), Ctor); + if (CXXBaseOrMemberInitializer *Value + = AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) { AllToInit.push_back(Value); } else { @@ -1299,7 +1324,12 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null"); CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context); if (!Ctor) { - Bases.push_back(Base); + Diag(Constructor->getLocation(), diag::err_missing_default_ctor) + << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) + << 0 << Base->getType(); + Diag(BaseDecl->getLocation(), diag::note_previous_class_decl) + << Context.getTagDeclType(BaseDecl); + HadError = true; continue; } @@ -1310,6 +1340,9 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, MarkDeclarationReferenced(Constructor->getLocation(), Ctor); + // FIXME: CXXBaseOrMemberInitializer should only contain a single + // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary. + ExprTemporaries.clear(); CXXBaseOrMemberInitializer *Member = new (Context) CXXBaseOrMemberInitializer(Base->getType(), CtorArgs.takeAs<Expr>(), @@ -1328,7 +1361,7 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, if (const RecordType *FieldClassType = Field->getType()->getAs<RecordType>()) { CXXRecordDecl *FieldClassDecl - = cast<CXXRecordDecl>(FieldClassType->getDecl()); + = cast<CXXRecordDecl>(FieldClassType->getDecl()); for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(), EA = FieldClassDecl->field_end(); FA != EA; FA++) { if (CXXBaseOrMemberInitializer *Value = AllBaseFields.lookup(*FA)) { @@ -1345,37 +1378,49 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, continue; } if (CXXBaseOrMemberInitializer *Value = AllBaseFields.lookup(*Field)) { - QualType FT = (*Field)->getType(); - if (const RecordType* RT = FT->getAs<RecordType>()) { - CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RT->getDecl()); - assert(FieldRecDecl && "SetBaseOrMemberInitializers - BaseDecl null"); - if (CXXConstructorDecl *Ctor = - FieldRecDecl->getDefaultConstructor(Context)) - MarkDeclarationReferenced(Value->getSourceLocation(), Ctor); - } AllToInit.push_back(Value); continue; } - if ((*Field)->getType()->isDependentType()) { - Fields.push_back(*Field); + if ((*Field)->getType()->isDependentType()) continue; - } QualType FT = Context.getBaseElementType((*Field)->getType()); if (const RecordType* RT = FT->getAs<RecordType>()) { CXXConstructorDecl *Ctor = cast<CXXRecordDecl>(RT->getDecl())->getDefaultConstructor(Context); if (!Ctor) { - Fields.push_back(*Field); + Diag(Constructor->getLocation(), diag::err_missing_default_ctor) + << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) + << 1 << (*Field)->getDeclName(); + Diag(Field->getLocation(), diag::note_field_decl); + Diag(RT->getDecl()->getLocation(), diag::note_previous_class_decl) + << Context.getTagDeclType(RT->getDecl()); + HadError = true; continue; } - + + if (FT.isConstQualified() && Ctor->isTrivial()) { + Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor) + << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) + << 1 << (*Field)->getDeclName(); + Diag((*Field)->getLocation(), diag::note_declared_at); + HadError = true; + } + + // Don't create initializers for trivial constructors, since they don't + // actually need to be run. + if (Ctor->isTrivial()) + continue; + ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this); if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0), Constructor->getLocation(), CtorArgs)) continue; + // FIXME: CXXBaseOrMemberInitializer should only contain a single + // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary. + ExprTemporaries.clear(); CXXBaseOrMemberInitializer *Member = new (Context) CXXBaseOrMemberInitializer(*Field,CtorArgs.takeAs<Expr>(), CtorArgs.size(), Ctor, @@ -1383,23 +1428,21 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, SourceLocation()); AllToInit.push_back(Member); - if (Ctor) - MarkDeclarationReferenced(Constructor->getLocation(), Ctor); - if (FT.isConstQualified() && (!Ctor || Ctor->isTrivial())) { - Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor) - << Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getDeclName(); - Diag((*Field)->getLocation(), diag::note_declared_at); - } + MarkDeclarationReferenced(Constructor->getLocation(), Ctor); } else if (FT->isReferenceType()) { Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor) - << Context.getTagDeclType(ClassDecl) << 0 << (*Field)->getDeclName(); + << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) + << 0 << (*Field)->getDeclName(); Diag((*Field)->getLocation(), diag::note_declared_at); + HadError = true; } else if (FT.isConstQualified()) { Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor) - << Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getDeclName(); + << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) + << 1 << (*Field)->getDeclName(); Diag((*Field)->getLocation(), diag::note_declared_at); + HadError = true; } } @@ -1413,29 +1456,8 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, for (unsigned Idx = 0; Idx < NumInitializers; ++Idx) baseOrMemberInitializers[Idx] = AllToInit[Idx]; } -} - -void -Sema::BuildBaseOrMemberInitializers(ASTContext &C, - CXXConstructorDecl *Constructor, - CXXBaseOrMemberInitializer **Initializers, - unsigned NumInitializers - ) { - llvm::SmallVector<CXXBaseSpecifier *, 4> Bases; - llvm::SmallVector<FieldDecl *, 4> Members; - SetBaseOrMemberInitializers(Constructor, - Initializers, NumInitializers, Bases, Members); - for (unsigned int i = 0; i < Bases.size(); i++) { - if (!Bases[i]->getType()->isDependentType()) - Diag(Bases[i]->getSourceRange().getBegin(), - diag::err_missing_default_constructor) << 0 << Bases[i]->getType(); - } - for (unsigned int i = 0; i < Members.size(); i++) { - if (!Members[i]->getType()->isDependentType()) - Diag(Members[i]->getLocation(), diag::err_missing_default_constructor) - << 1 << Members[i]->getType(); - } + return HadError; } static void *GetKeyForTopLevelField(FieldDecl *Field) { @@ -1462,7 +1484,7 @@ static void *GetKeyForMember(CXXBaseOrMemberInitializer *Member, if (Member->isMemberInitializer()) { FieldDecl *Field = Member->getMember(); - // After BuildBaseOrMemberInitializers call, Field is the anonymous union + // After SetBaseOrMemberInitializers call, Field is the anonymous union // data member of the class. Data member used in the initializer list is // in AnonUnionMember field. if (MemberMaybeAnon && Field->isAnonymousStructOrUnion()) @@ -1527,9 +1549,9 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, return; } - BuildBaseOrMemberInitializers(Context, Constructor, + SetBaseOrMemberInitializers(Constructor, reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits), - NumMemInits); + NumMemInits, false); if (Constructor->isDependentContext()) return; @@ -1612,77 +1634,63 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, } void -Sema::computeBaseOrMembersToDestroy(CXXDestructorDecl *Destructor) { - CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Destructor->getDeclContext()); - llvm::SmallVector<uintptr_t, 32> AllToDestruct; +Sema::MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor) { + // Ignore dependent destructors. + if (Destructor->isDependentContext()) + return; + + CXXRecordDecl *ClassDecl = Destructor->getParent(); - for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(), - E = ClassDecl->vbases_end(); VBase != E; ++VBase) { - if (VBase->getType()->isDependentType()) + // Non-static data members. + for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(), + E = ClassDecl->field_end(); I != E; ++I) { + FieldDecl *Field = *I; + + QualType FieldType = Context.getBaseElementType(Field->getType()); + + const RecordType* RT = FieldType->getAs<RecordType>(); + if (!RT) continue; - // Skip over virtual bases which have trivial destructors. - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl()); - if (BaseClassDecl->hasTrivialDestructor()) + + CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + if (FieldClassDecl->hasTrivialDestructor()) continue; - if (const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context)) - MarkDeclarationReferenced(Destructor->getLocation(), - const_cast<CXXDestructorDecl*>(Dtor)); - uintptr_t Member = - reinterpret_cast<uintptr_t>(VBase->getType().getTypePtr()) - | CXXDestructorDecl::VBASE; - AllToDestruct.push_back(Member); + const CXXDestructorDecl *Dtor = FieldClassDecl->getDestructor(Context); + MarkDeclarationReferenced(Destructor->getLocation(), + const_cast<CXXDestructorDecl*>(Dtor)); } - for (CXXRecordDecl::base_class_iterator Base = - ClassDecl->bases_begin(), + + // Bases. + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), E = ClassDecl->bases_end(); Base != E; ++Base) { + // Ignore virtual bases. if (Base->isVirtual()) continue; - if (Base->getType()->isDependentType()) - continue; - // Skip over virtual bases which have trivial destructors. + + // Ignore trivial destructors. CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); if (BaseClassDecl->hasTrivialDestructor()) continue; - if (const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context)) - MarkDeclarationReferenced(Destructor->getLocation(), - const_cast<CXXDestructorDecl*>(Dtor)); - uintptr_t Member = - reinterpret_cast<uintptr_t>(Base->getType().getTypePtr()) - | CXXDestructorDecl::DRCTNONVBASE; - AllToDestruct.push_back(Member); - } - - // non-static data members. - for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), - E = ClassDecl->field_end(); Field != E; ++Field) { - QualType FieldType = Context.getBaseElementType((*Field)->getType()); - - if (const RecordType* RT = FieldType->getAs<RecordType>()) { - // Skip over virtual bases which have trivial destructors. - CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); - if (FieldClassDecl->hasTrivialDestructor()) - continue; - if (const CXXDestructorDecl *Dtor = - FieldClassDecl->getDestructor(Context)) - MarkDeclarationReferenced(Destructor->getLocation(), - const_cast<CXXDestructorDecl*>(Dtor)); - uintptr_t Member = reinterpret_cast<uintptr_t>(*Field); - AllToDestruct.push_back(Member); - } + + const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context); + MarkDeclarationReferenced(Destructor->getLocation(), + const_cast<CXXDestructorDecl*>(Dtor)); } - - unsigned NumDestructions = AllToDestruct.size(); - if (NumDestructions > 0) { - Destructor->setNumBaseOrMemberDestructions(NumDestructions); - uintptr_t *BaseOrMemberDestructions = - new (Context) uintptr_t [NumDestructions]; - // Insert in reverse order. - for (int Idx = NumDestructions-1, i=0 ; Idx >= 0; --Idx) - BaseOrMemberDestructions[i++] = AllToDestruct[Idx]; - Destructor->setBaseOrMemberDestructions(BaseOrMemberDestructions); + + // Virtual bases. + for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(), + E = ClassDecl->vbases_end(); VBase != E; ++VBase) { + // Ignore trivial destructors. + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl()); + if (BaseClassDecl->hasTrivialDestructor()) + continue; + + const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context); + MarkDeclarationReferenced(Destructor->getLocation(), + const_cast<CXXDestructorDecl*>(Dtor)); } } @@ -1694,9 +1702,7 @@ void Sema::ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) { if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(CDtorDecl.getAs<Decl>())) - BuildBaseOrMemberInitializers(Context, - Constructor, - (CXXBaseOrMemberInitializer **)0, 0); + SetBaseOrMemberInitializers(Constructor, 0, 0, false); } namespace { @@ -1931,7 +1937,7 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, } if (RD->isAbstract()) - AbstractClassUsageDiagnoser(*this, RD); + (void)AbstractClassUsageDiagnoser(*this, RD); if (!RD->isDependentType() && !RD->isInvalidDecl()) AddImplicitlyDeclaredMembersToClass(RD); @@ -2334,13 +2340,18 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { if (!Constructor->isInvalidDecl() && ((Constructor->getNumParams() == 1) || (Constructor->getNumParams() > 1 && - Constructor->getParamDecl(1)->hasDefaultArg()))) { + Constructor->getParamDecl(1)->hasDefaultArg())) && + Constructor->getTemplateSpecializationKind() + != TSK_ImplicitInstantiation) { QualType ParamType = Constructor->getParamDecl(0)->getType(); QualType ClassTy = Context.getTagDeclType(ClassDecl); if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) { SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation(); Diag(ParamLoc, diag::err_constructor_byvalue_arg) << CodeModificationHint::CreateInsertion(ParamLoc, " const &"); + + // FIXME: Rather that making the constructor invalid, we should endeavor + // to fix the type. Constructor->setInvalidDecl(); } } @@ -2349,6 +2360,28 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { ClassDecl->addedConstructor(Context, Constructor); } +/// CheckDestructor - Checks a fully-formed destructor for +/// well-formedness, issuing any diagnostics required. +void Sema::CheckDestructor(CXXDestructorDecl *Destructor) { + CXXRecordDecl *RD = Destructor->getParent(); + + if (Destructor->isVirtual()) { + SourceLocation Loc; + + if (!Destructor->isImplicit()) + Loc = Destructor->getLocation(); + else + Loc = RD->getLocation(); + + // If we have a virtual destructor, look up the deallocation function + FunctionDecl *OperatorDelete = 0; + DeclarationName Name = + Context.DeclarationNames.getCXXOperatorName(OO_Delete); + if (!FindDeallocationFunction(Loc, RD, Name, OperatorDelete)) + Destructor->setOperatorDelete(OperatorDelete); + } +} + static inline bool FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) { return (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 && @@ -2606,7 +2639,8 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // in that declarative region, it is treated as an original-namespace-name. NamedDecl *PrevDecl - = LookupSingleName(DeclRegionScope, II, LookupOrdinaryName, true); + = LookupSingleName(DeclRegionScope, II, LookupOrdinaryName, + ForRedeclaration); if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) { // This is an extended namespace definition. @@ -2714,14 +2748,14 @@ Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S, UsingDirectiveDecl *UDir = 0; // Lookup namespace name. - LookupResult R; - LookupParsedName(R, S, &SS, NamespcName, LookupNamespaceName, false); - if (R.isAmbiguous()) { - DiagnoseAmbiguousLookup(R, NamespcName, IdentLoc); + LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName); + LookupParsedName(R, S, &SS); + if (R.isAmbiguous()) return DeclPtrTy(); - } + if (!R.empty()) { NamedDecl *NS = R.getFoundDecl(); + // FIXME: Namespace aliases! assert(isa<NamespaceDecl>(NS) && "expected namespace decl"); // C++ [namespace.udir]p1: // A using-directive specifies that the names in the nominated @@ -2776,7 +2810,8 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, const CXXScopeSpec &SS, UnqualifiedId &Name, AttributeList *AttrList, - bool IsTypeName) { + bool IsTypeName, + SourceLocation TypenameLoc) { assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); switch (Name.getKind()) { @@ -2802,9 +2837,11 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, } DeclarationName TargetName = GetNameFromUnqualifiedId(Name); - NamedDecl *UD = BuildUsingDeclaration(UsingLoc, SS, + NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS, Name.getSourceRange().getBegin(), - TargetName, AttrList, IsTypeName); + TargetName, AttrList, + /* IsInstantiation */ false, + IsTypeName, TypenameLoc); if (UD) { PushOnScopeChains(UD, S); UD->setAccess(AS); @@ -2813,12 +2850,46 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, return DeclPtrTy::make(UD); } -NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc, +/// Builds a shadow declaration corresponding to a 'using' declaration. +static UsingShadowDecl *BuildUsingShadowDecl(Sema &SemaRef, Scope *S, + AccessSpecifier AS, + UsingDecl *UD, NamedDecl *Orig) { + // FIXME: diagnose hiding, collisions + + // If we resolved to another shadow declaration, just coalesce them. + if (isa<UsingShadowDecl>(Orig)) { + Orig = cast<UsingShadowDecl>(Orig)->getTargetDecl(); + assert(!isa<UsingShadowDecl>(Orig) && "nested shadow declaration"); + } + + UsingShadowDecl *Shadow + = UsingShadowDecl::Create(SemaRef.Context, SemaRef.CurContext, + UD->getLocation(), UD, Orig); + UD->addShadowDecl(Shadow); + + if (S) + SemaRef.PushOnScopeChains(Shadow, S); + else + SemaRef.CurContext->addDecl(Shadow); + Shadow->setAccess(AS); + + return Shadow; +} + +/// Builds a using declaration. +/// +/// \param IsInstantiation - Whether this call arises from an +/// instantiation of an unresolved using declaration. We treat +/// the lookup differently for these declarations. +NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, + SourceLocation UsingLoc, const CXXScopeSpec &SS, SourceLocation IdentLoc, DeclarationName Name, AttributeList *AttrList, - bool IsTypeName) { + bool IsInstantiation, + bool IsTypeName, + SourceLocation TypenameLoc) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); assert(IdentLoc.isValid() && "Invalid TargetName location."); @@ -2833,14 +2904,20 @@ NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc, NestedNameSpecifier *NNS = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); - if (isUnknownSpecialization(SS)) { - return UnresolvedUsingDecl::Create(Context, CurContext, UsingLoc, - SS.getRange(), NNS, - IdentLoc, Name, IsTypeName); + DeclContext *LookupContext = computeDeclContext(SS); + if (!LookupContext) { + if (IsTypeName) { + return UnresolvedUsingTypenameDecl::Create(Context, CurContext, + UsingLoc, TypenameLoc, + SS.getRange(), NNS, + IdentLoc, Name); + } else { + return UnresolvedUsingValueDecl::Create(Context, CurContext, + UsingLoc, SS.getRange(), NNS, + IdentLoc, Name); + } } - DeclContext *LookupContext = 0; - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(CurContext)) { // C++0x N2914 [namespace.udecl]p3: // A using-declaration used as a member-declaration shall refer to a member @@ -2848,37 +2925,36 @@ NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc, // anonymous union that is a member of a base class of the class being // defined, or shall refer to an enumerator for an enumeration type that is // a member of a base class of the class being defined. - const Type *Ty = NNS->getAsType(); - if (!Ty || !IsDerivedFrom(Context.getTagDeclType(RD), QualType(Ty, 0))) { + + CXXRecordDecl *LookupRD = dyn_cast<CXXRecordDecl>(LookupContext); + if (!LookupRD || !RD->isDerivedFrom(LookupRD)) { Diag(SS.getRange().getBegin(), diag::err_using_decl_nested_name_specifier_is_not_a_base_class) << NNS << RD->getDeclName(); return 0; } - - QualType BaseTy = Context.getCanonicalType(QualType(Ty, 0)); - LookupContext = BaseTy->getAs<RecordType>()->getDecl(); } else { // C++0x N2914 [namespace.udecl]p8: // A using-declaration for a class member shall be a member-declaration. - if (NNS->getKind() == NestedNameSpecifier::TypeSpec) { + if (isa<CXXRecordDecl>(LookupContext)) { Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_class_member) << SS.getRange(); return 0; } - - // C++0x N2914 [namespace.udecl]p9: - // In a using-declaration, a prefix :: refers to the global namespace. - if (NNS->getKind() == NestedNameSpecifier::Global) - LookupContext = Context.getTranslationUnitDecl(); - else - LookupContext = NNS->getAsNamespace(); } + // Look up the target name. Unlike most lookups, we do not want to + // hide tag declarations: tag names are visible through the using + // declaration even if hidden by ordinary names. + LookupResult R(*this, Name, IdentLoc, LookupOrdinaryName); - // Lookup target name. - LookupResult R; - LookupQualifiedName(R, LookupContext, Name, LookupOrdinaryName); + // We don't hide tags behind ordinary decls if we're in a + // non-dependent context, but in a dependent context, this is + // important for the stability of two-phase lookup. + if (!IsInstantiation) + R.setHideTags(false); + + LookupQualifiedName(R, LookupContext); if (R.empty()) { Diag(IdentLoc, diag::err_no_member) @@ -2886,24 +2962,49 @@ NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc, return 0; } - // FIXME: handle ambiguity? - NamedDecl *ND = R.getAsSingleDecl(Context); - - if (IsTypeName && !isa<TypeDecl>(ND)) { - Diag(IdentLoc, diag::err_using_typename_non_type); + if (R.isAmbiguous()) return 0; + + if (IsTypeName) { + // If we asked for a typename and got a non-type decl, error out. + if (R.getResultKind() != LookupResult::Found + || !isa<TypeDecl>(R.getFoundDecl())) { + Diag(IdentLoc, diag::err_using_typename_non_type); + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + Diag((*I)->getUnderlyingDecl()->getLocation(), + diag::note_using_decl_target); + return 0; + } + } else { + // If we asked for a non-typename and we got a type, error out, + // but only if this is an instantiation of an unresolved using + // decl. Otherwise just silently find the type name. + if (IsInstantiation && + R.getResultKind() == LookupResult::Found && + isa<TypeDecl>(R.getFoundDecl())) { + Diag(IdentLoc, diag::err_using_dependent_value_is_type); + Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target); + return 0; + } } // C++0x N2914 [namespace.udecl]p6: // A using-declaration shall not name a namespace. - if (isa<NamespaceDecl>(ND)) { + if (R.getResultKind() == LookupResult::Found + && isa<NamespaceDecl>(R.getFoundDecl())) { Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace) << SS.getRange(); return 0; } - return UsingDecl::Create(Context, CurContext, IdentLoc, SS.getRange(), - ND->getLocation(), UsingLoc, ND, NNS, IsTypeName); + UsingDecl *UD = UsingDecl::Create(Context, CurContext, IdentLoc, + SS.getRange(), UsingLoc, NNS, Name, + IsTypeName); + + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + BuildUsingShadowDecl(*this, S, AS, UD, *I); + + return UD; } /// getNamespaceDecl - Returns the namespace a decl represents. If the decl @@ -2923,12 +3024,12 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, IdentifierInfo *Ident) { // Lookup the namespace name. - LookupResult R; - LookupParsedName(R, S, &SS, Ident, LookupNamespaceName, false); + LookupResult R(*this, Ident, IdentLoc, LookupNamespaceName); + LookupParsedName(R, S, &SS); // Check if we have a previous declaration with the same name. if (NamedDecl *PrevDecl - = LookupSingleName(S, Alias, LookupOrdinaryName, true)) { + = LookupSingleName(S, Alias, LookupOrdinaryName, ForRedeclaration)) { if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) { // We already have an alias with the same name that points to the same // namespace, so don't create a new one. @@ -2944,10 +3045,8 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, return DeclPtrTy(); } - if (R.isAmbiguous()) { - DiagnoseAmbiguousLookup(R, Ident, IdentLoc); + if (R.isAmbiguous()) return DeclPtrTy(); - } if (R.empty()) { Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange(); @@ -2973,76 +3072,22 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Constructor->getDeclContext()); assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor"); - // Before the implicitly-declared default constructor for a class is - // implicitly defined, all the implicitly-declared default constructors - // for its base class and its non-static data members shall have been - // implicitly defined. - bool err = false; - for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), - E = ClassDecl->bases_end(); Base != E; ++Base) { - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - if (!BaseClassDecl->hasTrivialConstructor()) { - if (CXXConstructorDecl *BaseCtor = - BaseClassDecl->getDefaultConstructor(Context)) - MarkDeclarationReferenced(CurrentLocation, BaseCtor); - else { - Diag(CurrentLocation, diag::err_defining_default_ctor) - << Context.getTagDeclType(ClassDecl) << 0 - << Context.getTagDeclType(BaseClassDecl); - Diag(BaseClassDecl->getLocation(), diag::note_previous_class_decl) - << Context.getTagDeclType(BaseClassDecl); - err = true; - } - } - } - for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), - E = ClassDecl->field_end(); Field != E; ++Field) { - QualType FieldType = Context.getCanonicalType((*Field)->getType()); - if (const ArrayType *Array = Context.getAsArrayType(FieldType)) - FieldType = Array->getElementType(); - if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { - CXXRecordDecl *FieldClassDecl - = cast<CXXRecordDecl>(FieldClassType->getDecl()); - if (!FieldClassDecl->hasTrivialConstructor()) { - if (CXXConstructorDecl *FieldCtor = - FieldClassDecl->getDefaultConstructor(Context)) - MarkDeclarationReferenced(CurrentLocation, FieldCtor); - else { - Diag(CurrentLocation, diag::err_defining_default_ctor) - << Context.getTagDeclType(ClassDecl) << 1 << - Context.getTagDeclType(FieldClassDecl); - Diag((*Field)->getLocation(), diag::note_field_decl); - Diag(FieldClassDecl->getLocation(), diag::note_previous_class_decl) - << Context.getTagDeclType(FieldClassDecl); - err = true; - } - } - } else if (FieldType->isReferenceType()) { - Diag(CurrentLocation, diag::err_unintialized_member) - << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName(); - Diag((*Field)->getLocation(), diag::note_declared_at); - err = true; - } else if (FieldType.isConstQualified()) { - Diag(CurrentLocation, diag::err_unintialized_member) - << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName(); - Diag((*Field)->getLocation(), diag::note_declared_at); - err = true; - } - } - if (!err) - Constructor->setUsed(); - else + + if (SetBaseOrMemberInitializers(Constructor, 0, 0, true)) { + Diag(CurrentLocation, diag::note_ctor_synthesized_at) + << Context.getTagDeclType(ClassDecl); Constructor->setInvalidDecl(); + } else { + Constructor->setUsed(); + } + return; } void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, CXXDestructorDecl *Destructor) { assert((Destructor->isImplicit() && !Destructor->isUsed()) && "DefineImplicitDestructor - call it for implicit default dtor"); - - CXXRecordDecl *ClassDecl - = cast<CXXRecordDecl>(Destructor->getDeclContext()); + CXXRecordDecl *ClassDecl = Destructor->getParent(); assert(ClassDecl && "DefineImplicitDestructor - invalid destructor"); // C++ [class.dtor] p5 // Before the implicitly-declared default destructor for a class is @@ -3399,6 +3444,107 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, /*DirectInit=*/true); } +/// \brief Add the applicable constructor candidates for an initialization +/// by constructor. +static void AddConstructorInitializationCandidates(Sema &SemaRef, + QualType ClassType, + Expr **Args, + unsigned NumArgs, + Sema::InitializationKind Kind, + OverloadCandidateSet &CandidateSet) { + // C++ [dcl.init]p14: + // If the initialization is direct-initialization, or if it is + // copy-initialization where the cv-unqualified version of the + // source type is the same class as, or a derived class of, the + // class of the destination, constructors are considered. The + // applicable constructors are enumerated (13.3.1.3), and the + // best one is chosen through overload resolution (13.3). The + // constructor so selected is called to initialize the object, + // with the initializer expression(s) as its argument(s). If no + // constructor applies, or the overload resolution is ambiguous, + // the initialization is ill-formed. + const RecordType *ClassRec = ClassType->getAs<RecordType>(); + assert(ClassRec && "Can only initialize a class type here"); + + // FIXME: When we decide not to synthesize the implicitly-declared + // constructors, we'll need to make them appear here. + + const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassRec->getDecl()); + DeclarationName ConstructorName + = SemaRef.Context.DeclarationNames.getCXXConstructorName( + SemaRef.Context.getCanonicalType(ClassType).getUnqualifiedType()); + DeclContext::lookup_const_iterator Con, ConEnd; + for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(ConstructorName); + Con != ConEnd; ++Con) { + // Find the constructor (which may be a template). + CXXConstructorDecl *Constructor = 0; + FunctionTemplateDecl *ConstructorTmpl= dyn_cast<FunctionTemplateDecl>(*Con); + if (ConstructorTmpl) + Constructor + = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl()); + else + Constructor = cast<CXXConstructorDecl>(*Con); + + if ((Kind == Sema::IK_Direct) || + (Kind == Sema::IK_Copy && + Constructor->isConvertingConstructor(/*AllowExplicit=*/false)) || + (Kind == Sema::IK_Default && Constructor->isDefaultConstructor())) { + if (ConstructorTmpl) + SemaRef.AddTemplateOverloadCandidate(ConstructorTmpl, false, 0, 0, + Args, NumArgs, CandidateSet); + else + SemaRef.AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet); + } + } +} + +/// \brief Attempt to perform initialization by constructor +/// (C++ [dcl.init]p14), which may occur as part of direct-initialization or +/// copy-initialization. +/// +/// This routine determines whether initialization by constructor is possible, +/// but it does not emit any diagnostics in the case where the initialization +/// is ill-formed. +/// +/// \param ClassType the type of the object being initialized, which must have +/// class type. +/// +/// \param Args the arguments provided to initialize the object +/// +/// \param NumArgs the number of arguments provided to initialize the object +/// +/// \param Kind the type of initialization being performed +/// +/// \returns the constructor used to initialize the object, if successful. +/// Otherwise, emits a diagnostic and returns NULL. +CXXConstructorDecl * +Sema::TryInitializationByConstructor(QualType ClassType, + Expr **Args, unsigned NumArgs, + SourceLocation Loc, + InitializationKind Kind) { + // Build the overload candidate set + OverloadCandidateSet CandidateSet; + AddConstructorInitializationCandidates(*this, ClassType, Args, NumArgs, Kind, + CandidateSet); + + // Determine whether we found a constructor we can use. + OverloadCandidateSet::iterator Best; + switch (BestViableFunction(CandidateSet, Loc, Best)) { + case OR_Success: + case OR_Deleted: + // We found a constructor. Return it. + return cast<CXXConstructorDecl>(Best->Function); + + case OR_No_Viable_Function: + case OR_Ambiguous: + // Overload resolution failed. Return nothing. + return 0; + } + + // Silence GCC warning + return 0; +} + /// \brief Perform initialization by constructor (C++ [dcl.init]p14), which /// may occur as part of direct-initialization or copy-initialization. /// @@ -3428,55 +3574,13 @@ Sema::PerformInitializationByConstructor(QualType ClassType, DeclarationName InitEntity, InitializationKind Kind, ASTOwningVector<&ActionBase::DeleteExpr> &ConvertedArgs) { - const RecordType *ClassRec = ClassType->getAs<RecordType>(); - assert(ClassRec && "Can only initialize a class type here"); + + // Build the overload candidate set Expr **Args = (Expr **)ArgsPtr.get(); unsigned NumArgs = ArgsPtr.size(); - - // C++ [dcl.init]p14: - // If the initialization is direct-initialization, or if it is - // copy-initialization where the cv-unqualified version of the - // source type is the same class as, or a derived class of, the - // class of the destination, constructors are considered. The - // applicable constructors are enumerated (13.3.1.3), and the - // best one is chosen through overload resolution (13.3). The - // constructor so selected is called to initialize the object, - // with the initializer expression(s) as its argument(s). If no - // constructor applies, or the overload resolution is ambiguous, - // the initialization is ill-formed. - const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassRec->getDecl()); OverloadCandidateSet CandidateSet; - - // Add constructors to the overload set. - DeclarationName ConstructorName - = Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(ClassType.getUnqualifiedType())); - DeclContext::lookup_const_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(ConstructorName); - Con != ConEnd; ++Con) { - // Find the constructor (which may be a template). - CXXConstructorDecl *Constructor = 0; - FunctionTemplateDecl *ConstructorTmpl= dyn_cast<FunctionTemplateDecl>(*Con); - if (ConstructorTmpl) - Constructor - = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl()); - else - Constructor = cast<CXXConstructorDecl>(*Con); - - if ((Kind == IK_Direct) || - (Kind == IK_Copy && - Constructor->isConvertingConstructor(/*AllowExplicit=*/false)) || - (Kind == IK_Default && Constructor->isDefaultConstructor())) { - if (ConstructorTmpl) - AddTemplateOverloadCandidate(ConstructorTmpl, false, 0, 0, - Args, NumArgs, CandidateSet); - else - AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet); - } - } - - // FIXME: When we decide not to synthesize the implicitly-declared - // constructors, we'll need to make them appear here. + AddConstructorInitializationCandidates(*this, ClassType, Args, NumArgs, Kind, + CandidateSet); OverloadCandidateSet::iterator Best; switch (BestViableFunction(CandidateSet, Loc, Best)) { @@ -3613,8 +3717,8 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, QualType T1 = Context.getCanonicalType(OrigT1); QualType T2 = Context.getCanonicalType(OrigT2); - QualType UnqualT1 = T1.getUnqualifiedType(); - QualType UnqualT2 = T2.getUnqualifiedType(); + QualType UnqualT1 = T1.getLocalUnqualifiedType(); + QualType UnqualT2 = T2.getLocalUnqualifiedType(); // C++ [dcl.init.ref]p4: // Given types "cv1 T1" and "cv2 T2," "cv1 T1" is @@ -3663,12 +3767,15 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, /// When @p AllowExplicit, we also permit explicit user-defined /// conversion functions. /// When @p ForceRValue, we unconditionally treat the initializer as an rvalue. +/// When @p IgnoreBaseAccess, we don't do access control on to-base conversion. +/// This is used when this is called from a C-style cast. bool Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, SourceLocation DeclLoc, bool SuppressUserConversions, bool AllowExplicit, bool ForceRValue, - ImplicitConversionSequence *ICS) { + ImplicitConversionSequence *ICS, + bool IgnoreBaseAccess) { assert(DeclType->isReferenceType() && "Reference init needs a reference"); QualType T1 = DeclType->getAs<ReferenceType>()->getPointeeType(); @@ -3827,6 +3934,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, ICS->UserDefined.Before = Best->Conversions[0].Standard; ICS->UserDefined.After = Best->FinalConversion; ICS->UserDefined.ConversionFunction = Best->Function; + ICS->UserDefined.EllipsisConversion = false; assert(ICS->UserDefined.After.ReferenceBinding && ICS->UserDefined.After.DirectBinding && "Expected a direct reference binding!"); @@ -3882,7 +3990,8 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, // actually happens. if (DerivedToBase) return CheckDerivedToBaseConversion(T2, T1, DeclLoc, - Init->getSourceRange()); + Init->getSourceRange(), + IgnoreBaseAccess); else return false; } @@ -4051,9 +4160,28 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { // found in the rest of this subclause do not apply to them unless // explicitly stated in 3.7.3. // FIXME: Write a separate routine for checking this. For now, just allow it. - if (Op == OO_New || Op == OO_Array_New || - Op == OO_Delete || Op == OO_Array_Delete) + if (Op == OO_Delete || Op == OO_Array_Delete) return false; + + if (Op == OO_New || Op == OO_Array_New) { + bool ret = false; + if (FunctionDecl::param_iterator Param = FnDecl->param_begin()) { + QualType SizeTy = Context.getCanonicalType(Context.getSizeType()); + QualType T = Context.getCanonicalType((*Param)->getType()); + if (!T->isDependentType() && SizeTy != T) { + Diag(FnDecl->getLocation(), + diag::err_operator_new_param_type) << FnDecl->getDeclName() + << SizeTy; + ret = true; + } + } + QualType ResultTy = Context.getCanonicalType(FnDecl->getResultType()); + if (!ResultTy->isDependentType() && ResultTy != Context.VoidPtrTy) + return Diag(FnDecl->getLocation(), + diag::err_operator_new_result_type) << FnDecl->getDeclName() + << static_cast<QualType>(Context.VoidPtrTy); + return ret; + } // C++ [over.oper]p6: // An operator function shall either be a non-static member @@ -4182,7 +4310,6 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { assert(isa<CXXMethodDecl>(FnDecl) && "Overloaded = not member, but not filtered."); CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl); - Method->setCopyAssignment(true); Method->getParent()->addedAssignmentOperator(Context, Method); } @@ -4549,8 +4676,8 @@ Sema::ActOnFriendFunctionDecl(Scope *S, // FIXME: handle dependent contexts if (!DC) return DeclPtrTy(); - LookupResult R; - LookupQualifiedName(R, DC, Name, LookupOrdinaryName, true); + LookupResult R(*this, Name, Loc, LookupOrdinaryName, ForRedeclaration); + LookupQualifiedName(R, DC); PrevDecl = R.getAsSingleDecl(Context); // If searching in that context implicitly found a declaration in @@ -4584,8 +4711,8 @@ Sema::ActOnFriendFunctionDecl(Scope *S, while (DC->isRecord()) DC = DC->getParent(); - LookupResult R; - LookupQualifiedName(R, DC, Name, LookupOrdinaryName, true); + LookupResult R(*this, Name, Loc, LookupOrdinaryName, ForRedeclaration); + LookupQualifiedName(R, DC); PrevDecl = R.getAsSingleDecl(Context); // TODO: decide what we think about using declarations. @@ -4697,7 +4824,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, QualType COldTy = Context.getCanonicalType(OldTy); if (CNewTy == COldTy && - CNewTy.getCVRQualifiers() == COldTy.getCVRQualifiers()) + CNewTy.getLocalCVRQualifiers() == COldTy.getLocalCVRQualifiers()) return false; // Check if the return types are covariant @@ -4726,7 +4853,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, return true; } - if (NewClassTy.getUnqualifiedType() != OldClassTy.getUnqualifiedType()) { + if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) { // Check if the new class derives from the old class. if (!IsDerivedFrom(NewClassTy, OldClassTy)) { Diag(New->getLocation(), @@ -4748,7 +4875,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, } // The qualifiers of the return types must be the same. - if (CNewTy.getCVRQualifiers() != COldTy.getCVRQualifiers()) { + if (CNewTy.getLocalCVRQualifiers() != COldTy.getLocalCVRQualifiers()) { Diag(New->getLocation(), diag::err_covariant_return_type_different_qualifications) << New->getDeclName() << NewTy << OldTy; |