diff options
author | Roman Divacky <rdivacky@FreeBSD.org> | 2010-01-15 15:39:40 +0000 |
---|---|---|
committer | Roman Divacky <rdivacky@FreeBSD.org> | 2010-01-15 15:39:40 +0000 |
commit | ee791dde723a2089c681d2ab6a9d4f96379d5f49 (patch) | |
tree | a6082d4d1d1e9ddaea09a6a04bb4a47da95d642d /lib/Sema/SemaDeclCXX.cpp | |
parent | abe15e553e58165e7692c0d0842865c488ed7b45 (diff) | |
download | src-ee791dde723a2089c681d2ab6a9d4f96379d5f49.tar.gz src-ee791dde723a2089c681d2ab6a9d4f96379d5f49.zip |
Notes
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 244 |
1 files changed, 172 insertions, 72 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 204d7764682b..a81a04e45e18 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -270,18 +270,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); - + // FIXME: If we knew where the '=' was, we could easily provide a fix-it + // hint here. Alternatively, we could walk the type-source information + // for NewParam to find the last source location in the type... but it + // isn't worth the effort right now. This is the kind of test case that + // is hard to get right: + + // int f(int); + // void g(int (*fp)(int) = f); + // void g(int (*fp)(int) = &f); Diag(NewParam->getLocation(), diag::err_param_default_argument_redefinition) - << NewParam->getDefaultArgRange() - << CodeModificationHint::CreateRemoval(SourceRange(Begin, - NewParam->getLocEnd())); + << NewParam->getDefaultArgRange(); // Look for the function declaration where the default argument was // actually written, which may be a declaration prior to Old. @@ -424,6 +424,8 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) { /// the innermost class. bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *, const CXXScopeSpec *SS) { + assert(getLangOptions().CPlusPlus && "No class names in C!"); + CXXRecordDecl *CurDecl; if (SS && SS->isSet() && !SS->isInvalid()) { DeclContext *DC = computeDeclContext(*SS, true); @@ -1072,6 +1074,8 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, << MemberOrBase << true << R.getLookupName() << CodeModificationHint::CreateReplacement(R.getNameLoc(), R.getLookupName().getAsString()); + Diag(Member->getLocation(), diag::note_previous_decl) + << Member->getDeclName(); return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc, LParenLoc, RParenLoc); @@ -1089,7 +1093,14 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, << MemberOrBase << false << R.getLookupName() << CodeModificationHint::CreateReplacement(R.getNameLoc(), R.getLookupName().getAsString()); - + + const CXXBaseSpecifier *BaseSpec = DirectBaseSpec? DirectBaseSpec + : VirtualBaseSpec; + Diag(BaseSpec->getSourceRange().getBegin(), + diag::note_base_class_specified_here) + << BaseSpec->getType() + << BaseSpec->getSourceRange(); + TyD = Type; } } @@ -2054,7 +2065,7 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { if (!Record->isDependentType()) AddImplicitlyDeclaredMembersToClass(Record); - + if (Record->isInvalidDecl()) return; @@ -2734,18 +2745,23 @@ Sema::DeclPtrTy Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { << ClassType << ConvType; } - if (Conversion->getPreviousDeclaration()) { - const NamedDecl *ExpectedPrevDecl = Conversion->getPreviousDeclaration(); + if (Conversion->getPrimaryTemplate()) { + // ignore specializations + } else if (Conversion->getPreviousDeclaration()) { if (FunctionTemplateDecl *ConversionTemplate - = Conversion->getDescribedFunctionTemplate()) - ExpectedPrevDecl = ConversionTemplate->getPreviousDeclaration(); - if (ClassDecl->replaceConversion(ExpectedPrevDecl, Conversion)) + = Conversion->getDescribedFunctionTemplate()) { + if (ClassDecl->replaceConversion( + ConversionTemplate->getPreviousDeclaration(), + ConversionTemplate)) + return DeclPtrTy::make(ConversionTemplate); + } else if (ClassDecl->replaceConversion(Conversion->getPreviousDeclaration(), + Conversion)) return DeclPtrTy::make(Conversion); assert(Conversion->isInvalidDecl() && "Conversion should not get here."); } else if (FunctionTemplateDecl *ConversionTemplate = Conversion->getDescribedFunctionTemplate()) ClassDecl->addConversionFunction(ConversionTemplate); - else if (!Conversion->getPrimaryTemplate()) // ignore specializations + else ClassDecl->addConversionFunction(Conversion); return DeclPtrTy::make(Conversion); @@ -2986,6 +3002,7 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, break; case UnqualifiedId::IK_ConstructorName: + case UnqualifiedId::IK_ConstructorTemplateId: // C++0x inherited constructors. if (getLangOptions().CPlusPlus0x) break; @@ -4184,7 +4201,7 @@ Sema::PerformInitializationByConstructor(QualType ClassType, else Diag(Loc, diag::err_ovl_no_viable_function_in_init) << ClassType << Range; - PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); + PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs); return 0; case OR_Ambiguous: @@ -4192,7 +4209,7 @@ Sema::PerformInitializationByConstructor(QualType ClassType, Diag(Loc, diag::err_ovl_ambiguous_init) << InitEntity << Range; else Diag(Loc, diag::err_ovl_ambiguous_init) << ClassType << Range; - PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); + PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, Args, NumArgs); return 0; case OR_Deleted: @@ -4207,7 +4224,7 @@ Sema::PerformInitializationByConstructor(QualType ClassType, << Best->Function->isDeleted() << RD->getDeclName() << Range; } - PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); + PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs); return 0; } @@ -4373,8 +4390,10 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, = CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase); // Most paths end in a failed conversion. - if (ICS) - ICS->ConversionKind = ImplicitConversionSequence::BadConversion; + if (ICS) { + ICS->setBad(); + ICS->Bad.init(BadConversionSequence::no_conversion, Init, DeclType); + } // C++ [dcl.init.ref]p5: // A reference to type "cv1 T1" is initialized by an expression @@ -4412,7 +4431,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, // has a type that is a derived class of the parameter type, // in which case the implicit conversion sequence is a // derived-to-base Conversion (13.3.3.1). - ICS->ConversionKind = ImplicitConversionSequence::StandardConversion; + ICS->setStandard(); ICS->Standard.First = ICK_Identity; ICS->Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity; ICS->Standard.Third = ICK_Identity; @@ -4497,7 +4516,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, // conversion or, if the conversion function returns an // entity of a type that is a derived class of the parameter // type, a derived-to-base Conversion. - ICS->ConversionKind = ImplicitConversionSequence::UserDefinedConversion; + ICS->setUserDefined(); ICS->UserDefined.Before = Best->Conversions[0].Standard; ICS->UserDefined.After = Best->FinalConversion; ICS->UserDefined.ConversionFunction = Best->Function; @@ -4523,15 +4542,16 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, case OR_Ambiguous: if (ICS) { + ICS->setAmbiguous(); for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(); Cand != CandidateSet.end(); ++Cand) if (Cand->Viable) - ICS->ConversionFunctionSet.push_back(Cand->Function); + ICS->Ambiguous.addConversion(Cand->Function); break; } Diag(DeclLoc, diag::err_ref_init_ambiguous) << DeclType << Init->getType() << Init->getSourceRange(); - PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); + PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, &Init, 1); return true; case OR_No_Viable_Function: @@ -4600,7 +4620,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, if (InitLvalue != Expr::LV_Valid && T2->isRecordType() && RefRelationship >= Ref_Compatible_With_Added_Qualification) { if (ICS) { - ICS->ConversionKind = ImplicitConversionSequence::StandardConversion; + ICS->setStandard(); ICS->Standard.First = ICK_Identity; ICS->Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity; ICS->Standard.Third = ICK_Identity; @@ -4672,30 +4692,27 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, /*InOverloadResolution=*/false); // Of course, that's still a reference binding. - if (ICS->ConversionKind == ImplicitConversionSequence::StandardConversion) { + if (ICS->isStandard()) { ICS->Standard.ReferenceBinding = true; ICS->Standard.RRefBinding = isRValRef; - } else if (ICS->ConversionKind == - ImplicitConversionSequence::UserDefinedConversion) { + } else if (ICS->isUserDefined()) { ICS->UserDefined.After.ReferenceBinding = true; ICS->UserDefined.After.RRefBinding = isRValRef; } - return ICS->ConversionKind == ImplicitConversionSequence::BadConversion; + return ICS->isBad(); } else { ImplicitConversionSequence Conversions; bool badConversion = PerformImplicitConversion(Init, T1, AA_Initializing, false, false, Conversions); if (badConversion) { - if ((Conversions.ConversionKind == - ImplicitConversionSequence::BadConversion) - && !Conversions.ConversionFunctionSet.empty()) { + if (Conversions.isAmbiguous()) { Diag(DeclLoc, diag::err_lvalue_to_rvalue_ambig_ref) << Init->getSourceRange(); - for (int j = Conversions.ConversionFunctionSet.size()-1; + for (int j = Conversions.Ambiguous.conversions().size()-1; j >= 0; j--) { - FunctionDecl *Func = Conversions.ConversionFunctionSet[j]; - Diag(Func->getLocation(), diag::err_ovl_candidate); + FunctionDecl *Func = Conversions.Ambiguous.conversions()[j]; + NoteOverloadCandidate(Func); } } else { @@ -4993,6 +5010,88 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { return false; } +/// CheckLiteralOperatorDeclaration - Check whether the declaration +/// of this literal operator function is well-formed. If so, returns +/// false; otherwise, emits appropriate diagnostics and returns true. +bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { + DeclContext *DC = FnDecl->getDeclContext(); + Decl::Kind Kind = DC->getDeclKind(); + if (Kind != Decl::TranslationUnit && Kind != Decl::Namespace && + Kind != Decl::LinkageSpec) { + Diag(FnDecl->getLocation(), diag::err_literal_operator_outside_namespace) + << FnDecl->getDeclName(); + return true; + } + + bool Valid = false; + + // FIXME: Check for the one valid template signature + // template <char...> type operator "" name(); + + if (FunctionDecl::param_iterator Param = FnDecl->param_begin()) { + // Check the first parameter + QualType T = (*Param)->getType(); + + // unsigned long long int and long double are allowed, but only + // alone. + // We also allow any character type; their omission seems to be a bug + // in n3000 + if (Context.hasSameType(T, Context.UnsignedLongLongTy) || + Context.hasSameType(T, Context.LongDoubleTy) || + Context.hasSameType(T, Context.CharTy) || + Context.hasSameType(T, Context.WCharTy) || + Context.hasSameType(T, Context.Char16Ty) || + Context.hasSameType(T, Context.Char32Ty)) { + if (++Param == FnDecl->param_end()) + Valid = true; + goto FinishedParams; + } + + // Otherwise it must be a pointer to const; let's strip those. + const PointerType *PT = T->getAs<PointerType>(); + if (!PT) + goto FinishedParams; + T = PT->getPointeeType(); + if (!T.isConstQualified()) + goto FinishedParams; + T = T.getUnqualifiedType(); + + // Move on to the second parameter; + ++Param; + + // If there is no second parameter, the first must be a const char * + if (Param == FnDecl->param_end()) { + if (Context.hasSameType(T, Context.CharTy)) + Valid = true; + goto FinishedParams; + } + + // const char *, const wchar_t*, const char16_t*, and const char32_t* + // are allowed as the first parameter to a two-parameter function + if (!(Context.hasSameType(T, Context.CharTy) || + Context.hasSameType(T, Context.WCharTy) || + Context.hasSameType(T, Context.Char16Ty) || + Context.hasSameType(T, Context.Char32Ty))) + goto FinishedParams; + + // The second and final parameter must be an std::size_t + T = (*Param)->getType().getUnqualifiedType(); + if (Context.hasSameType(T, Context.getSizeType()) && + ++Param == FnDecl->param_end()) + Valid = true; + } + + // FIXME: This diagnostic is absolutely terrible. +FinishedParams: + if (!Valid) { + Diag(FnDecl->getLocation(), diag::err_literal_operator_params) + << FnDecl->getDeclName(); + return true; + } + + return false; +} + /// ActOnStartLinkageSpecification - Parsed the beginning of a C++ /// linkage specification, including the language and (if present) /// the '{'. ExternLoc is the location of the 'extern', LangLoc is @@ -5693,55 +5792,56 @@ void Sema::MaybeMarkVirtualMembersReferenced(SourceLocation Loc, if (!RD->isDynamicClass()) return; - if (!MD->isOutOfLine()) { - // The only inline functions we care about are constructors. We also defer - // marking the virtual members as referenced until we've reached the end - // of the translation unit. We do this because we need to know the key - // function of the class in order to determine the key function. - if (isa<CXXConstructorDecl>(MD)) - ClassesWithUnmarkedVirtualMembers.insert(std::make_pair(RD, Loc)); + // Ignore declarations that are not definitions. + if (!MD->isThisDeclarationADefinition()) return; - } - const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD); - - if (!KeyFunction) { - // This record does not have a key function, so we assume that the vtable - // will be emitted when it's used by the constructor. - if (!isa<CXXConstructorDecl>(MD)) + if (isa<CXXConstructorDecl>(MD)) { + switch (MD->getParent()->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + // Classes that aren't instantiations of templates don't need their + // virtual methods marked until we see the definition of the key + // function. + return; + + case TSK_ImplicitInstantiation: + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + // This is a constructor of a class template; mark all of the virtual + // members as referenced to ensure that they get instantiatied. + break; + } + } else if (!MD->isOutOfLine()) { + // Consider only out-of-line definitions of member functions. When we see + // an inline definition, it's too early to compute the key function. + return; + } else if (const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD)) { + // If this is not the key function, we don't need to mark virtual members. + if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl()) return; - } else if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl()) { - // We don't have the right key function. + } else { + // The class has no key function, so we've already noted that we need to + // mark the virtual members of this class. return; } - // Mark the members as referenced. - MarkVirtualMembersReferenced(Loc, RD); - ClassesWithUnmarkedVirtualMembers.erase(RD); + // We will need to mark all of the virtual members as referenced to build the + // vtable. + ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(RD, Loc)); } bool Sema::ProcessPendingClassesWithUnmarkedVirtualMembers() { if (ClassesWithUnmarkedVirtualMembers.empty()) return false; - for (std::map<CXXRecordDecl *, SourceLocation>::iterator i = - ClassesWithUnmarkedVirtualMembers.begin(), - e = ClassesWithUnmarkedVirtualMembers.end(); i != e; ++i) { - CXXRecordDecl *RD = i->first; - - const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD); - if (KeyFunction) { - // We know that the class has a key function. If the key function was - // declared in this translation unit, then it the class decl would not - // have been in the ClassesWithUnmarkedVirtualMembers map. - continue; - } - - SourceLocation Loc = i->second; + while (!ClassesWithUnmarkedVirtualMembers.empty()) { + CXXRecordDecl *RD = ClassesWithUnmarkedVirtualMembers.back().first; + SourceLocation Loc = ClassesWithUnmarkedVirtualMembers.back().second; + ClassesWithUnmarkedVirtualMembers.pop_back(); MarkVirtualMembersReferenced(Loc, RD); } - ClassesWithUnmarkedVirtualMembers.clear(); return true; } |