diff options
-rw-r--r-- | include/clang/Sema/Sema.h | 60 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 16 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 9 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 69 | ||||
-rw-r--r-- | test/SemaCXX/type-traits.cpp | 7 |
5 files changed, 122 insertions, 39 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 5db08ba830..a905efe836 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -234,17 +234,23 @@ public: private: Sema &S; DeclContext *SavedContext; - + unsigned SavedParsingDeclDepth; + public: - ContextRAII(Sema &S, DeclContext *ContextToPush) - : S(S), SavedContext(S.CurContext) { + ContextRAII(Sema &S, DeclContext *ContextToPush, + unsigned ParsingDeclDepth = 0) + : S(S), SavedContext(S.CurContext), + SavedParsingDeclDepth(S.ParsingDeclDepth) + { assert(ContextToPush && "pushing null context"); S.CurContext = ContextToPush; + S.ParsingDeclDepth = 0; } void pop() { if (!SavedContext) return; S.CurContext = SavedContext; + S.ParsingDeclDepth = SavedParsingDeclDepth; SavedContext = 0; } @@ -2803,6 +2809,10 @@ public: /// A flag to suppress access checking. bool SuppressAccessChecking; + /// \brief When true, access checking violations are treated as SFINAE + /// failures rather than hard errors. + bool AccessCheckingSFINAE; + void ActOnStartSuppressingAccessChecks(); void ActOnStopSuppressingAccessChecks(); @@ -3708,6 +3718,13 @@ public: llvm::SmallVector<ActiveTemplateInstantiation, 16> ActiveTemplateInstantiations; + /// \brief Whether we are in a SFINAE context that is not associated with + /// template instantiation. + /// + /// This is used when setting up a SFINAE trap (\c see SFINAETrap) outside + /// of a template instantiation or template argument deduction. + bool InNonInstantiationSFINAEContext; + /// \brief The number of ActiveTemplateInstantiation entries in /// \c ActiveTemplateInstantiations that are not actual instantiations and, /// therefore, should not be counted as part of the instantiation depth. @@ -3729,7 +3746,7 @@ public: /// should be instantiated as themselves. Otherwise, the index specifies /// which argument within the parameter pack will be used for substitution. int ArgumentPackSubstitutionIndex; - + /// \brief RAII object used to change the argument pack substitution index /// within a \c Sema object. /// @@ -3855,6 +3872,7 @@ public: private: Sema &SemaRef; bool Invalid; + bool SavedInNonInstantiationSFINAEContext; bool CheckInstantiationDepth(SourceLocation PointOfInstantiation, SourceRange InstantiationRange); @@ -3870,23 +3888,39 @@ public: /// template argument substitution failures are not considered /// errors. /// - /// \returns The nearest template-deduction context object, if we are in a - /// SFINAE context, which can be used to capture diagnostics that will be - /// suppressed. Otherwise, returns NULL to indicate that we are not within a - /// SFINAE context. - sema::TemplateDeductionInfo *isSFINAEContext() const; + /// \returns An empty \c llvm::Optional if we're not in a SFINAE context. + /// Otherwise, contains a pointer that, if non-NULL, contains the nearest + /// template-deduction context object, which can be used to capture + /// diagnostics that will be suppressed. + llvm::Optional<sema::TemplateDeductionInfo *> isSFINAEContext() const; /// \brief RAII class used to determine whether SFINAE has /// trapped any errors that occur during template argument - /// deduction. + /// deduction.` class SFINAETrap { Sema &SemaRef; unsigned PrevSFINAEErrors; + bool PrevInNonInstantiationSFINAEContext; + bool PrevAccessCheckingSFINAE; + public: - explicit SFINAETrap(Sema &SemaRef) - : SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors) { } + explicit SFINAETrap(Sema &SemaRef, bool AccessCheckingSFINAE = false) + : SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors), + PrevInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext), + PrevAccessCheckingSFINAE(SemaRef.AccessCheckingSFINAE) + { + if (!SemaRef.isSFINAEContext()) + SemaRef.InNonInstantiationSFINAEContext = true; + SemaRef.AccessCheckingSFINAE = AccessCheckingSFINAE; + } - ~SFINAETrap() { SemaRef.NumSFINAEErrors = PrevSFINAEErrors; } + ~SFINAETrap() { + SemaRef.NumSFINAEErrors = PrevSFINAEErrors; + SemaRef.InNonInstantiationSFINAEContext + = PrevInNonInstantiationSFINAEContext; + SemaRef.AccessCheckingSFINAE = PrevAccessCheckingSFINAE; + } /// \brief Determine whether any SFINAE errors have been trapped. bool hasErrorOccurred() const { diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index e37f617549..44bb71e57b 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -139,7 +139,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, IdResolver(pp.getLangOptions()), CXXTypeInfoDecl(0), MSVCGuidDecl(0), GlobalNewDeleteDeclared(false), CompleteTranslationUnit(CompleteTranslationUnit), - NumSFINAEErrors(0), SuppressAccessChecking(false), + NumSFINAEErrors(0), SuppressAccessChecking(false), + AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1), CurrentInstantiationScope(0), TyposCorrected(0), AnalysisWarnings(*this) @@ -450,14 +451,18 @@ Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() { if (!isActive()) return; - if (TemplateDeductionInfo *Info = SemaRef.isSFINAEContext()) { + if (llvm::Optional<TemplateDeductionInfo*> Info = SemaRef.isSFINAEContext()) { switch (DiagnosticIDs::getDiagnosticSFINAEResponse(getDiagID())) { - case DiagnosticIDs::SFINAE_AccessControl: case DiagnosticIDs::SFINAE_Report: // Fall through; we'll report the diagnostic below. break; - + case DiagnosticIDs::SFINAE_AccessControl: + // Unless access checking is specifically called out as a SFINAE + // error, report this diagnostic. + if (!SemaRef.AccessCheckingSFINAE) + break; + case DiagnosticIDs::SFINAE_SubstitutionFailure: // Count this failure so that we know that template argument deduction // has failed. @@ -473,7 +478,8 @@ Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() { FlushCounts(); DiagnosticInfo DiagInfo(&SemaRef.Diags); - Info->addSuppressedDiagnostic(DiagInfo.getLocation(), + if (*Info) + (*Info)->addSuppressedDiagnostic(DiagInfo.getLocation(), PartialDiagnostic(DiagInfo, SemaRef.Context.getDiagAllocator())); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index ca104ef581..cf2e10d531 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2537,13 +2537,14 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT, InitializationKind Kind(InitializationKind::CreateCopy(KeyLoc, SourceLocation())); - // Perform the initialization within a SFINAE trap. - // FIXME: We don't implement the access-checking bits yet, because we don't - // handle access control as part of SFINAE. - Sema::SFINAETrap SFINAE(Self); + // Perform the initialization within a SFINAE trap at translation unit + // scope. + Sema::SFINAETrap SFINAE(Self, /*AccessCheckingSFINAE=*/true); + Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl()); InitializationSequence Init(Self, To, Kind, &FromPtr, 1); if (Init.getKind() == InitializationSequence::FailedSequence) return false; + ExprResult Result = Init.Perform(Self, To, Kind, MultiExprArg(&FromPtr, 1)); return !Result.isInvalid() && !SFINAE.hasErrorOccurred(); } diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 45fde296e3..f58e744578 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -147,7 +147,10 @@ Sema::InstantiatingTemplate:: InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, Decl *Entity, SourceRange InstantiationRange) - : SemaRef(SemaRef) { + : SemaRef(SemaRef), + SavedInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext) +{ Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange); if (!Invalid) { @@ -158,6 +161,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, Inst.TemplateArgs = 0; Inst.NumTemplateArgs = 0; Inst.InstantiationRange = InstantiationRange; + SemaRef.InNonInstantiationSFINAEContext = false; SemaRef.ActiveTemplateInstantiations.push_back(Inst); } } @@ -168,8 +172,10 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, SourceRange InstantiationRange) - : SemaRef(SemaRef) { - + : SemaRef(SemaRef), + SavedInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext) +{ Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange); if (!Invalid) { @@ -181,6 +187,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, Inst.TemplateArgs = TemplateArgs; Inst.NumTemplateArgs = NumTemplateArgs; Inst.InstantiationRange = InstantiationRange; + SemaRef.InNonInstantiationSFINAEContext = false; SemaRef.ActiveTemplateInstantiations.push_back(Inst); } } @@ -193,8 +200,10 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, ActiveTemplateInstantiation::InstantiationKind Kind, sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange) - : SemaRef(SemaRef) { - + : SemaRef(SemaRef), + SavedInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext) +{ Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange); if (!Invalid) { @@ -206,6 +215,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, Inst.NumTemplateArgs = NumTemplateArgs; Inst.DeductionInfo = &DeductionInfo; Inst.InstantiationRange = InstantiationRange; + SemaRef.InNonInstantiationSFINAEContext = false; SemaRef.ActiveTemplateInstantiations.push_back(Inst); if (!Inst.isInstantiationRecord()) @@ -220,8 +230,10 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, unsigned NumTemplateArgs, sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange) - : SemaRef(SemaRef) { - + : SemaRef(SemaRef), + SavedInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext) +{ Invalid = false; ActiveTemplateInstantiation Inst; @@ -232,6 +244,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, Inst.NumTemplateArgs = NumTemplateArgs; Inst.DeductionInfo = &DeductionInfo; Inst.InstantiationRange = InstantiationRange; + SemaRef.InNonInstantiationSFINAEContext = false; SemaRef.ActiveTemplateInstantiations.push_back(Inst); assert(!Inst.isInstantiationRecord()); @@ -244,8 +257,10 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, SourceRange InstantiationRange) - : SemaRef(SemaRef) { - + : SemaRef(SemaRef), + SavedInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext) +{ Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange); if (!Invalid) { @@ -257,6 +272,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, Inst.TemplateArgs = TemplateArgs; Inst.NumTemplateArgs = NumTemplateArgs; Inst.InstantiationRange = InstantiationRange; + SemaRef.InNonInstantiationSFINAEContext = false; SemaRef.ActiveTemplateInstantiations.push_back(Inst); } } @@ -267,7 +283,11 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, NonTypeTemplateParmDecl *Param, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, - SourceRange InstantiationRange) : SemaRef(SemaRef) { + SourceRange InstantiationRange) + : SemaRef(SemaRef), + SavedInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext) +{ Invalid = false; ActiveTemplateInstantiation Inst; @@ -278,6 +298,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, Inst.TemplateArgs = TemplateArgs; Inst.NumTemplateArgs = NumTemplateArgs; Inst.InstantiationRange = InstantiationRange; + SemaRef.InNonInstantiationSFINAEContext = false; SemaRef.ActiveTemplateInstantiations.push_back(Inst); assert(!Inst.isInstantiationRecord()); @@ -290,7 +311,11 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateTemplateParmDecl *Param, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, - SourceRange InstantiationRange) : SemaRef(SemaRef) { + SourceRange InstantiationRange) + : SemaRef(SemaRef), + SavedInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext) +{ Invalid = false; ActiveTemplateInstantiation Inst; Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution; @@ -300,6 +325,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, Inst.TemplateArgs = TemplateArgs; Inst.NumTemplateArgs = NumTemplateArgs; Inst.InstantiationRange = InstantiationRange; + SemaRef.InNonInstantiationSFINAEContext = false; SemaRef.ActiveTemplateInstantiations.push_back(Inst); assert(!Inst.isInstantiationRecord()); @@ -312,7 +338,11 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, NamedDecl *Param, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, - SourceRange InstantiationRange) : SemaRef(SemaRef) { + SourceRange InstantiationRange) + : SemaRef(SemaRef), + SavedInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext) +{ Invalid = false; ActiveTemplateInstantiation Inst; @@ -323,6 +353,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, Inst.TemplateArgs = TemplateArgs; Inst.NumTemplateArgs = NumTemplateArgs; Inst.InstantiationRange = InstantiationRange; + SemaRef.InNonInstantiationSFINAEContext = false; SemaRef.ActiveTemplateInstantiations.push_back(Inst); assert(!Inst.isInstantiationRecord()); @@ -335,7 +366,8 @@ void Sema::InstantiatingTemplate::Clear() { assert(SemaRef.NonInstantiationEntries > 0); --SemaRef.NonInstantiationEntries; } - + SemaRef.InNonInstantiationSFINAEContext + = SavedInNonInstantiationSFINAEContext; SemaRef.ActiveTemplateInstantiations.pop_back(); Invalid = true; } @@ -530,8 +562,11 @@ void Sema::PrintInstantiationStack() { } } -TemplateDeductionInfo *Sema::isSFINAEContext() const { +llvm::Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const { using llvm::SmallVector; + if (InNonInstantiationSFINAEContext) + return llvm::Optional<TemplateDeductionInfo *>(0); + for (SmallVector<ActiveTemplateInstantiation, 16>::const_reverse_iterator Active = ActiveTemplateInstantiations.rbegin(), ActiveEnd = ActiveTemplateInstantiations.rend(); @@ -539,10 +574,10 @@ TemplateDeductionInfo *Sema::isSFINAEContext() const { ++Active) { switch(Active->Kind) { - case ActiveTemplateInstantiation::TemplateInstantiation: case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation: + case ActiveTemplateInstantiation::TemplateInstantiation: // This is a template instantiation, so there is no SFINAE. - return 0; + return llvm::Optional<TemplateDeductionInfo *>(); case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution: @@ -561,7 +596,7 @@ TemplateDeductionInfo *Sema::isSFINAEContext() const { } } - return 0; + return llvm::Optional<TemplateDeductionInfo *>(); } /// \brief Retrieve the depth and index of a parameter pack. diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index 54d1236dd8..0ecec44963 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -502,6 +502,12 @@ struct FromInt { FromInt(int); }; struct ToInt { operator int(); }; typedef void Function(); +void is_convertible_to(); +class PrivateCopy { + PrivateCopy(const PrivateCopy&); + friend void is_convertible_to(); +}; + void is_convertible_to() { int t01[T(__is_convertible_to(Int, Int))]; int t02[F(__is_convertible_to(Int, IntAr))]; @@ -524,4 +530,5 @@ void is_convertible_to() { int t19[T(__is_convertible_to(IntAr&, const IntAr&))]; int t20[F(__is_convertible_to(const IntAr&, IntAr&))]; int t21[F(__is_convertible_to(Function, Function))]; + int t22[F(__is_convertible_to(PrivateCopy, PrivateCopy))]; } |