diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2009-11-05 17:18:09 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2009-11-05 17:18:09 +0000 |
commit | b3a51061b1b9c4add078237850649f7c9efb13ab (patch) | |
tree | 8b316eca843681b024034db1125707173b9adb4a /lib/Sema/SemaDeclCXX.cpp | |
parent | b6d5e15aae202f157c6cd63da8fa4b089e7b31e9 (diff) | |
download | FreeBSD-src-b3a51061b1b9c4add078237850649f7c9efb13ab.zip FreeBSD-src-b3a51061b1b9c4add078237850649f7c9efb13ab.tar.gz |
Update clang to r86140.
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 148 |
1 files changed, 120 insertions, 28 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index bc25513..b8977cf 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -971,10 +971,70 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, RParenLoc, ClassDecl); } +/// Checks an initializer expression for use of uninitialized fields, such as +/// containing the field that is being initialized. Returns true if there is an +/// uninitialized field was used an updates the SourceLocation parameter; false +/// otherwise. +static bool InitExprContainsUninitializedFields(const Stmt* S, + const FieldDecl* LhsField, + SourceLocation* L) { + const MemberExpr* ME = dyn_cast<MemberExpr>(S); + if (ME) { + const NamedDecl* RhsField = ME->getMemberDecl(); + if (RhsField == LhsField) { + // Initializing a field with itself. Throw a warning. + // But wait; there are exceptions! + // Exception #1: The field may not belong to this record. + // e.g. Foo(const Foo& rhs) : A(rhs.A) {} + const Expr* base = ME->getBase(); + if (base != NULL && !isa<CXXThisExpr>(base->IgnoreParenCasts())) { + // Even though the field matches, it does not belong to this record. + return false; + } + // None of the exceptions triggered; return true to indicate an + // uninitialized field was used. + *L = ME->getMemberLoc(); + return true; + } + } + bool found = false; + for (Stmt::const_child_iterator it = S->child_begin(); + it != S->child_end() && found == false; + ++it) { + if (isa<CallExpr>(S)) { + // Do not descend into function calls or constructors, as the use + // of an uninitialized field may be valid. One would have to inspect + // the contents of the function/ctor to determine if it is safe or not. + // i.e. Pass-by-value is never safe, but pass-by-reference and pointers + // may be safe, depending on what the function/ctor does. + continue; + } + found = InitExprContainsUninitializedFields(*it, LhsField, L); + } + return found; +} + Sema::MemInitResult Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs, SourceLocation IdLoc, SourceLocation RParenLoc) { + // Diagnose value-uses of fields to initialize themselves, e.g. + // foo(foo) + // where foo is not also a parameter to the constructor. + // TODO: implement -Wuninitialized and fold this into that framework. + for (unsigned i = 0; i < NumArgs; ++i) { + SourceLocation L; + if (InitExprContainsUninitializedFields(Args[i], Member, &L)) { + // FIXME: Return true in the case when other fields are used before being + // uninitialized. For example, let this field be the i'th field. When + // initializing the i'th field, throw a warning if any of the >= i'th + // fields are used, as they are not yet initialized. + // Right now we are only handling the case where the i'th field uses + // itself in its initializer. + Diag(L, diag::warn_field_is_uninit); + } + } + bool HasDependentArg = false; for (unsigned i = 0; i < NumArgs; i++) HasDependentArg |= Args[i]->isTypeDependent(); @@ -985,7 +1045,9 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args, FieldType = Array->getElementType(); if (FieldType->isDependentType()) { // Can't check init for dependent type. - } else if (FieldType->getAs<RecordType>()) { + } else if (FieldType->isRecordType()) { + // Member is a record (struct/union/class), so pass the initializer + // arguments down to the record's constructor. if (!HasDependentArg) { ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); @@ -1005,6 +1067,8 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args, } } } else if (NumArgs != 1 && NumArgs != 0) { + // The member type is not a record type (or an array of record + // types), so it can be only be default- or copy-initialized. return Diag(IdLoc, diag::err_mem_initializer_mismatch) << Member->getDeclName() << SourceRange(IdLoc, RParenLoc); } else if (!HasDependentArg) { @@ -1158,7 +1222,7 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, // On seeing one dependent type, we should essentially exit this routine // while preserving user-declared initializer list. When this routine is // called during instantiatiation process, this routine will rebuild the - // oderdered initializer list correctly. + // ordered initializer list correctly. // If we have a dependent base initialization, we can't determine the // association between initializers and bases; just dump the known @@ -1293,11 +1357,16 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, continue; } + if ((*Field)->getType()->isDependentType()) { + Fields.push_back(*Field); + continue; + } + QualType FT = Context.getBaseElementType((*Field)->getType()); if (const RecordType* RT = FT->getAs<RecordType>()) { CXXConstructorDecl *Ctor = cast<CXXRecordDecl>(RT->getDecl())->getDefaultConstructor(Context); - if (!Ctor && !FT->isDependentType()) { + if (!Ctor) { Fields.push_back(*Field); continue; } @@ -1357,12 +1426,16 @@ Sema::BuildBaseOrMemberInitializers(ASTContext &C, SetBaseOrMemberInitializers(Constructor, Initializers, NumInitializers, Bases, Members); - for (unsigned int i = 0; i < Bases.size(); i++) - Diag(Bases[i]->getSourceRange().getBegin(), - diag::err_missing_default_constructor) << 0 << Bases[i]->getType(); - for (unsigned int i = 0; i < Members.size(); i++) - Diag(Members[i]->getLocation(), diag::err_missing_default_constructor) - << 1 << Members[i]->getType(); + 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(); + } } static void *GetKeyForTopLevelField(FieldDecl *Field) { @@ -1405,6 +1478,7 @@ static void *GetKeyForMember(CXXBaseOrMemberInitializer *Member, return GetKeyForBase(QualType(Member->getBaseClass(), 0)); } +/// ActOnMemInitializers - Handle the member initializers for a constructor. void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, SourceLocation ColonLoc, MemInitTy **MemInits, unsigned NumMemInits) { @@ -2700,22 +2774,37 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, const CXXScopeSpec &SS, - SourceLocation IdentLoc, - IdentifierInfo *TargetName, - OverloadedOperatorKind Op, + UnqualifiedId &Name, AttributeList *AttrList, bool IsTypeName) { - assert((TargetName || Op) && "Invalid TargetName."); assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); - DeclarationName Name; - if (TargetName) - Name = TargetName; - else - Name = Context.DeclarationNames.getCXXOperatorName(Op); - - NamedDecl *UD = BuildUsingDeclaration(UsingLoc, SS, IdentLoc, - Name, AttrList, IsTypeName); + switch (Name.getKind()) { + case UnqualifiedId::IK_Identifier: + case UnqualifiedId::IK_OperatorFunctionId: + case UnqualifiedId::IK_ConversionFunctionId: + break; + + case UnqualifiedId::IK_ConstructorName: + Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_constructor) + << SS.getRange(); + return DeclPtrTy(); + + case UnqualifiedId::IK_DestructorName: + Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_destructor) + << SS.getRange(); + return DeclPtrTy(); + + case UnqualifiedId::IK_TemplateId: + Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_template_id) + << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc); + return DeclPtrTy(); + } + + DeclarationName TargetName = GetNameFromUnqualifiedId(Name); + NamedDecl *UD = BuildUsingDeclaration(UsingLoc, SS, + Name.getSourceRange().getBegin(), + TargetName, AttrList, IsTypeName); if (UD) { PushOnScopeChains(UD, S); UD->setAccess(AS); @@ -3515,14 +3604,15 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, /// type, and the first type (T1) is the pointee type of the reference /// type being initialized. Sema::ReferenceCompareResult -Sema::CompareReferenceRelationship(QualType T1, QualType T2, +Sema::CompareReferenceRelationship(SourceLocation Loc, + QualType OrigT1, QualType OrigT2, bool& DerivedToBase) { - assert(!T1->isReferenceType() && + assert(!OrigT1->isReferenceType() && "T1 must be the pointee type of the reference type"); - assert(!T2->isReferenceType() && "T2 cannot be a reference type"); + assert(!OrigT2->isReferenceType() && "T2 cannot be a reference type"); - T1 = Context.getCanonicalType(T1); - T2 = Context.getCanonicalType(T2); + QualType T1 = Context.getCanonicalType(OrigT1); + QualType T2 = Context.getCanonicalType(OrigT2); QualType UnqualT1 = T1.getUnqualifiedType(); QualType UnqualT2 = T2.getUnqualifiedType(); @@ -3532,7 +3622,9 @@ Sema::CompareReferenceRelationship(QualType T1, QualType T2, // T1 is a base class of T2. if (UnqualT1 == UnqualT2) DerivedToBase = false; - else if (IsDerivedFrom(UnqualT2, UnqualT1)) + else if (!RequireCompleteType(Loc, OrigT1, PDiag()) && + !RequireCompleteType(Loc, OrigT2, PDiag()) && + IsDerivedFrom(UnqualT2, UnqualT1)) DerivedToBase = true; else return Ref_Incompatible; @@ -3608,7 +3700,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, Expr::isLvalueResult InitLvalue = ForceRValue ? Expr::LV_InvalidExpression : Init->isLvalue(Context); ReferenceCompareResult RefRelationship - = CompareReferenceRelationship(T1, T2, DerivedToBase); + = CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase); // Most paths end in a failed conversion. if (ICS) |