diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 55 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 18 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 25 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 55 |
8 files changed, 131 insertions, 57 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index a0046a2caa1..1b3572a6498 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/APFloat.h" #include "clang/Sema/CXXFieldCollector.h" +#include "clang/Sema/TemplateDeduction.h" #include "clang/Sema/ExternalSemaSource.h" #include "clang/Sema/ObjCMethodList.h" #include "clang/Sema/PrettyDeclStackTrace.h" @@ -433,6 +434,41 @@ NamedDecl *Sema::getCurFunctionOrMethodDecl() { } Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() { + if (!isActive()) + return; + + if (TemplateDeductionInfo *Info = SemaRef.isSFINAEContext()) { + switch (Diagnostic::getDiagnosticSFINAEResponse(getDiagID())) { + case Diagnostic::SFINAE_Report: + // Fall through; we'll report the diagnostic below. + break; + + case Diagnostic::SFINAE_SubstitutionFailure: + // Count this failure so that we know that template argument deduction + // has failed. + ++SemaRef.NumSFINAEErrors; + SemaRef.Diags.setLastDiagnosticIgnored(); + SemaRef.Diags.Clear(); + Clear(); + return; + + case Diagnostic::SFINAE_Suppress: + // Make a copy of this suppressed diagnostic and store it with the + // template-deduction information; + DiagnosticInfo DiagInfo(&SemaRef.Diags); + Info->addSuppressedDiagnostic(DiagInfo.getLocation(), + PartialDiagnostic(DiagInfo, + SemaRef.Context.getDiagAllocator())); + + // Suppress this diagnostic. + SemaRef.Diags.setLastDiagnosticIgnored(); + SemaRef.Diags.Clear(); + Clear(); + return; + } + } + + // Emit the diagnostic. if (!this->Emit()) return; @@ -451,25 +487,6 @@ Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() { } Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID) { - if (isSFINAEContext()) { - switch (Diagnostic::getDiagnosticSFINAEResponse(DiagID)) { - case Diagnostic::SFINAE_Report: - // Fall through; we'll report the diagnostic below. - break; - - case Diagnostic::SFINAE_SubstitutionFailure: - // Count this failure so that we know that template argument deduction - // has failed. - ++NumSFINAEErrors; - // Fall through - - case Diagnostic::SFINAE_Suppress: - // Suppress this diagnostic. - Diags.setLastDiagnosticIgnored(); - return SemaDiagnosticBuilder(*this); - } - } - DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID); return SemaDiagnosticBuilder(DB, *this, DiagID); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 68bb2b07233..609465c5052 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -56,6 +56,24 @@ using namespace sema; /// referenced), false otherwise. /// bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { + if (getLangOptions().CPlusPlus && isa<FunctionDecl>(D)) { + // If there were any diagnostics suppressed by template argument deduction, + // emit them now. + llvm::DenseMap<Decl *, llvm::SmallVector<PartialDiagnosticAt, 1> >::iterator + Pos = SuppressedDiagnostics.find(D->getCanonicalDecl()); + if (Pos != SuppressedDiagnostics.end()) { + llvm::SmallVectorImpl<PartialDiagnosticAt> &Suppressed = Pos->second; + for (unsigned I = 0, N = Suppressed.size(); I != N; ++I) + Diag(Suppressed[I].first, Suppressed[I].second); + + // Clear out the list of suppressed diagnostics, so that we don't emit + // them again for this specialization. However, we don't remove this + // entry from the table, because we want to avoid ever emitting these + // diagnostics again. + Suppressed.clear(); + } + } + // See if the decl is deprecated. if (const DeprecatedAttr *DA = D->getAttr<DeprecatedAttr>()) EmitDeprecationWarning(D, DA->getMessage(), Loc); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 04c15e3f001..00a3e27edc9 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1551,9 +1551,11 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, return ExprError(); if (!RD->hasTrivialDestructor()) - if (const CXXDestructorDecl *Dtor = LookupDestructor(RD)) + if (CXXDestructorDecl *Dtor = LookupDestructor(RD)) { MarkDeclarationReferenced(StartLoc, const_cast<CXXDestructorDecl*>(Dtor)); + DiagnoseUseOfDecl(Dtor, StartLoc); + } } if (!OperatorDelete) { @@ -1829,7 +1831,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin())) return true; - + From = FixOverloadedFunctionReference(From, Found, Fn); FromType = From->getType(); } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 7f0f2767c64..1e48930f972 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3765,6 +3765,7 @@ InitializationSequence::Perform(Sema &S, S.CheckDestructorAccess(CurInitExpr->getLocStart(), Destructor, S.PDiag(diag::err_access_dtor_temp) << T); S.MarkDeclarationReferenced(CurInitExpr->getLocStart(), Destructor); + S.DiagnoseUseOfDecl(Destructor, CurInitExpr->getLocStart()); } } @@ -3858,7 +3859,8 @@ InitializationSequence::Perform(Sema &S, unsigned NumExprs = ConstructorArgs.size(); Expr **Exprs = (Expr **)ConstructorArgs.take(); S.MarkDeclarationReferenced(Loc, Constructor); - + S.DiagnoseUseOfDecl(Constructor, Loc); + TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo(); if (!TSInfo) TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 1437238f3bf..078669a556a 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -5489,6 +5489,7 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc, // placement new (5.3.4), as well as non-default initialization (8.5). if (Best->Function) S.MarkDeclarationReferenced(Loc, Best->Function); + return OR_Success; } @@ -6313,7 +6314,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, // whose type matches exactly. llvm::SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches; llvm::SmallVector<FunctionDecl *, 4> NonMatches; - + bool FoundNonTemplateFunction = false; for (UnresolvedSetIterator I = OvlExpr->decls_begin(), E = OvlExpr->decls_end(); I != E; ++I) { @@ -6344,7 +6345,6 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, // resulting template argument list is used to generate a single // function template specialization, which is added to the set of // overloaded functions considered. - // FIXME: We don't really want to build the specialization here, do we? FunctionDecl *Specialization = 0; TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc()); if (TemplateDeductionResult Result @@ -6355,10 +6355,10 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, } else { // Template argument deduction ensures that we have an exact match. // This function template specicalization works. + Specialization = cast<FunctionDecl>(Specialization->getCanonicalDecl()); assert(FunctionType == Context.getCanonicalType(Specialization->getType())); - Matches.push_back(std::make_pair(I.getPair(), - cast<FunctionDecl>(Specialization->getCanonicalDecl()))); + Matches.push_back(std::make_pair(I.getPair(), Specialization)); } continue; @@ -6403,10 +6403,11 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, return 0; } else if (Matches.size() == 1) { FunctionDecl *Result = Matches[0].second; - FoundResult = Matches[0].first; + FoundResult = Matches[0].first; MarkDeclarationReferenced(From->getLocStart(), Result); - if (Complain) + if (Complain) { CheckAddressOfMemberAccess(OvlExpr, Matches[0].first); + } return Result; } @@ -6441,10 +6442,8 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, MarkDeclarationReferenced(From->getLocStart(), *Result); FoundResult = Matches[Result - MatchesCopy.begin()].first; - if (Complain) { + if (Complain) CheckUnresolvedAccess(*this, OvlExpr, FoundResult); - DiagnoseUseOfDecl(FoundResult, OvlExpr->getNameLoc()); - } return cast<FunctionDecl>(*Result); } @@ -6464,10 +6463,8 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, if (Matches.size() == 1) { MarkDeclarationReferenced(From->getLocStart(), Matches[0].second); FoundResult = Matches[0].first; - if (Complain) { + if (Complain) CheckUnresolvedAccess(*this, OvlExpr, Matches[0].first); - DiagnoseUseOfDecl(Matches[0].first, OvlExpr->getNameLoc()); - } return cast<FunctionDecl>(Matches[0].second); } @@ -6543,7 +6540,7 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) { Matched = Specialization; } - + return Matched; } @@ -6734,7 +6731,7 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, case OR_Success: { FunctionDecl *FDecl = Best->Function; CheckUnresolvedLookupAccess(ULE, Best->FoundDecl); - DiagnoseUseOfDecl(Best->FoundDecl, ULE->getNameLoc()); + DiagnoseUseOfDecl(FDecl? FDecl : Best->FoundDecl, ULE->getNameLoc()); Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl); return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc); } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index ec928ea4b7b..a569a966fa3 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2363,6 +2363,9 @@ bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param, // template-argument for a template type-parameter. // C++0x allows these, and even in C++03 we allow them as an extension with // a warning. + // + // FIXME: We're not handling the "type compounded from any of these types" + // case. SourceRange SR = ArgInfo->getTypeLoc().getSourceRange(); if (!LangOpts.CPlusPlus0x) { const TagType *Tag = 0; diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index ce3748b901a..ae9052b704a 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -1127,7 +1127,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, return Result; InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial, - Deduced.data(), Deduced.size()); + Deduced.data(), Deduced.size(), Info); if (Inst) return TDK_InstantiationDepth; @@ -1214,7 +1214,8 @@ Sema::SubstituteExplicitTemplateArguments( // and then substitute them into the function parameter types. InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(), FunctionTemplate, Deduced.data(), Deduced.size(), - ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution); + ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution, + Info); if (Inst) return TDK_InstantiationDepth; @@ -1374,7 +1375,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, // actual function declaration. InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(), FunctionTemplate, Deduced.data(), Deduced.size(), - ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution); + ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution, + Info); if (Inst) return TDK_InstantiationDepth; @@ -1429,7 +1431,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, TemplateArgumentLoc Arg = getTrivialTemplateArgumentLoc(*this, Deduced[I], NTTPType, - SourceLocation()); + Info.getLocation()); // Check the template argument, converting it as necessary. if (CheckTemplateArgument(Param, Arg, @@ -1515,6 +1517,18 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, return TDK_SubstitutionFailure; } + // If we suppressed any diagnostics while performing template argument + // deduction, and if we haven't already instantiated this declaration, + // keep track of these diagnostics. They'll be emitted if this specialization + // is actually used. + if (Info.diag_begin() != Info.diag_end()) { + llvm::DenseMap<Decl *, llvm::SmallVector<PartialDiagnosticAt, 1> >::iterator + Pos = SuppressedDiagnostics.find(Specialization->getCanonicalDecl()); + if (Pos == SuppressedDiagnostics.end()) + SuppressedDiagnostics[Specialization->getCanonicalDecl()] + .append(Info.diag_begin(), Info.diag_end()); + } + return TDK_Success; } diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 98b8ccd8d85..2bc0e40b39a 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -148,7 +148,6 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, Decl *Entity, SourceRange InstantiationRange) : SemaRef(SemaRef) { - Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange); if (!Invalid) { @@ -192,6 +191,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, ActiveTemplateInstantiation::InstantiationKind Kind, + sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange) : SemaRef(SemaRef) { @@ -204,6 +204,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, Inst.Entity = reinterpret_cast<uintptr_t>(FunctionTemplate); Inst.TemplateArgs = TemplateArgs; Inst.NumTemplateArgs = NumTemplateArgs; + Inst.DeductionInfo = &DeductionInfo; Inst.InstantiationRange = InstantiationRange; SemaRef.ActiveTemplateInstantiations.push_back(Inst); @@ -217,6 +218,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, ClassTemplatePartialSpecializationDecl *PartialSpec, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, + sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange) : SemaRef(SemaRef) { @@ -228,6 +230,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec); Inst.TemplateArgs = TemplateArgs; Inst.NumTemplateArgs = NumTemplateArgs; + Inst.DeductionInfo = &DeductionInfo; Inst.InstantiationRange = InstantiationRange; SemaRef.ActiveTemplateInstantiations.push_back(Inst); @@ -516,7 +519,7 @@ void Sema::PrintInstantiationStack() { } } -bool Sema::isSFINAEContext() const { +TemplateDeductionInfo *Sema::isSFINAEContext() const { using llvm::SmallVector; for (SmallVector<ActiveTemplateInstantiation, 16>::const_reverse_iterator Active = ActiveTemplateInstantiations.rbegin(), @@ -528,7 +531,7 @@ bool Sema::isSFINAEContext() const { case ActiveTemplateInstantiation::TemplateInstantiation: case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation: // This is a template instantiation, so there is no SFINAE. - return false; + return 0; case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution: @@ -542,11 +545,12 @@ bool Sema::isSFINAEContext() const { case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution: // We're either substitution explicitly-specified template arguments // or deduced template arguments, so SFINAE applies. - return true; + assert(Active->DeductionInfo && "Missing deduction info pointer"); + return Active->DeductionInfo; } } - return false; + return 0; } //===----------------------------------------------------------------------===/ @@ -1255,6 +1259,16 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, return Invalid; } +namespace { + /// \brief A partial specialization whose template arguments have matched + /// a given template-id. + struct PartialSpecMatchResult { + ClassTemplatePartialSpecializationDecl *Partial; + TemplateArgumentList *Args; + llvm::SmallVector<PartialDiagnosticAt, 1> Diagnostics; + }; +} + bool Sema::InstantiateClassTemplateSpecialization( SourceLocation PointOfInstantiation, @@ -1304,8 +1318,7 @@ Sema::InstantiateClassTemplateSpecialization( // matching the template arguments of the class template // specialization with the template argument lists of the partial // specializations. - typedef std::pair<ClassTemplatePartialSpecializationDecl *, - TemplateArgumentList *> MatchResult; + typedef PartialSpecMatchResult MatchResult; llvm::SmallVector<MatchResult, 4> Matched; llvm::SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs; Template->getPartialSpecializations(PartialSpecs); @@ -1320,7 +1333,10 @@ Sema::InstantiateClassTemplateSpecialization( // diagnostics, later. (void)Result; } else { - Matched.push_back(std::make_pair(Partial, Info.take())); + Matched.push_back(PartialSpecMatchResult()); + Matched.back().Partial = Partial; + Matched.back().Args = Info.take(); + Matched.back().Diagnostics.append(Info.diag_begin(), Info.diag_end()); } } @@ -1341,9 +1357,9 @@ Sema::InstantiateClassTemplateSpecialization( for (llvm::SmallVector<MatchResult, 4>::iterator P = Best + 1, PEnd = Matched.end(); P != PEnd; ++P) { - if (getMoreSpecializedPartialSpecialization(P->first, Best->first, + if (getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial, PointOfInstantiation) - == P->first) + == P->Partial) Best = P; } @@ -1354,9 +1370,9 @@ Sema::InstantiateClassTemplateSpecialization( PEnd = Matched.end(); P != PEnd; ++P) { if (P != Best && - getMoreSpecializedPartialSpecialization(P->first, Best->first, + getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial, PointOfInstantiation) - != Best->first) { + != Best->Partial) { Ambiguous = true; break; } @@ -1372,16 +1388,17 @@ Sema::InstantiateClassTemplateSpecialization( for (llvm::SmallVector<MatchResult, 4>::iterator P = Matched.begin(), PEnd = Matched.end(); P != PEnd; ++P) - Diag(P->first->getLocation(), diag::note_partial_spec_match) - << getTemplateArgumentBindingsText(P->first->getTemplateParameters(), - *P->second); + Diag(P->Partial->getLocation(), diag::note_partial_spec_match) + << getTemplateArgumentBindingsText( + P->Partial->getTemplateParameters(), + *P->Args); return true; } } // Instantiate using the best class template partial specialization. - ClassTemplatePartialSpecializationDecl *OrigPartialSpec = Best->first; + ClassTemplatePartialSpecializationDecl *OrigPartialSpec = Best->Partial; while (OrigPartialSpec->getInstantiatedFromMember()) { // If we've found an explicit specialization of this class template, // stop here and use that as the pattern. @@ -1392,7 +1409,11 @@ Sema::InstantiateClassTemplateSpecialization( } Pattern = OrigPartialSpec; - ClassTemplateSpec->setInstantiationOf(Best->first, Best->second); + ClassTemplateSpec->setInstantiationOf(Best->Partial, Best->Args); + + // Report any suppressed diagnostics. + for (unsigned I = 0, N = Best->Diagnostics.size(); I != N; ++I) + Diag(Best->Diagnostics[I].first, Best->Diagnostics[I].second); } else { // -- If no matches are found, the instantiation is generated // from the primary template. |