diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaCast.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 11 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 57 |
4 files changed, 67 insertions, 15 deletions
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index d87be3b0aeb..5099867b199 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -2236,6 +2236,16 @@ void CastOperation::CheckCStyleCast() { return; } + // Overloads are allowed with C extensions, so we need to support them. + if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { + DeclAccessPair DAP; + if (FunctionDecl *FD = Self.ResolveAddressOfOverloadedFunction( + SrcExpr.get(), DestType, /*Complain=*/true, DAP)) + SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr.get(), DAP, FD); + else + return; + assert(SrcExpr.isUsable()); + } SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get()); if (SrcExpr.isInvalid()) return; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 3c916a30d17..d640a126989 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7274,6 +7274,15 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, // structures. // FIXME: We also fall through for atomics; not sure what should // happen there, though. + } else if (RHS.get()->getType() == Context.OverloadTy) { + // As a set of extensions to C, we support overloading on functions. These + // functions need to be resolved here. + DeclAccessPair DAP; + if (FunctionDecl *FD = ResolveAddressOfOverloadedFunction( + RHS.get(), LHSType, /*Complain=*/false, DAP)) + RHS = FixOverloadedFunctionReference(RHS.get(), DAP, FD); + else + return Incompatible; } // C99 6.5.16.1p1: the left operand is a pointer and the right is @@ -11986,7 +11995,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, if (SecondType == Context.OverloadTy) NoteAllOverloadCandidates(OverloadExpr::find(SrcExpr).Expression, - FirstType); + FirstType, /*TakingAddress=*/true); if (CheckInferredResultType) EmitRelatedResultTypeNote(SrcExpr); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 74db24f28dc..461b3b648dc 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -6599,6 +6599,8 @@ InitializationSequence::Perform(Sema &S, case SK_CAssignment: { QualType SourceType = CurInit.get()->getType(); + // Save off the initial CurInit in case we need to emit a diagnostic + ExprResult InitialCurInit = CurInit; ExprResult Result = CurInit; Sema::AssignConvertType ConvTy = S.CheckSingleAssignmentConstraints(Step->Type, Result, true, @@ -6621,7 +6623,7 @@ InitializationSequence::Perform(Sema &S, bool Complained; if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(), Step->Type, SourceType, - CurInit.get(), + InitialCurInit.get(), getAssignmentAction(Entity, true), &Complained)) { PrintInitLocationNote(S, Entity); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index b646c853561..44cb166f25b 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -2508,7 +2508,8 @@ enum { ft_parameter_arity, ft_parameter_mismatch, ft_return_type, - ft_qualifer_mismatch + ft_qualifer_mismatch, + ft_addr_enable_if }; /// HandleFunctionTypeMismatch - Gives diagnostic information for differeing @@ -8683,20 +8684,37 @@ void MaybeEmitInheritedConstructorNote(Sema &S, Decl *Fn) { } // end anonymous namespace +static bool isFunctionAlwaysEnabled(const ASTContext &Ctx, + const FunctionDecl *FD) { + for (auto *EnableIf : FD->specific_attrs<EnableIfAttr>()) { + bool AlwaysTrue; + if (!EnableIf->getCond()->EvaluateAsBooleanCondition(AlwaysTrue, Ctx)) + return false; + if (!AlwaysTrue) + return false; + } + return true; +} + // Notes the location of an overload candidate. -void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType) { +void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType, + bool TakingAddress) { std::string FnDesc; OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Fn, FnDesc); PartialDiagnostic PD = PDiag(diag::note_ovl_candidate) << (unsigned) K << FnDesc; - HandleFunctionTypeMismatch(PD, Fn->getType(), DestType); + if (TakingAddress && !isFunctionAlwaysEnabled(Context, Fn)) + PD << ft_addr_enable_if; + else + HandleFunctionTypeMismatch(PD, Fn->getType(), DestType); Diag(Fn->getLocation(), PD); MaybeEmitInheritedConstructorNote(*this, Fn); } // Notes the location of all overload candidates designated through // OverloadedExpr -void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr, QualType DestType) { +void Sema::NoteAllOverloadCandidates(Expr *OverloadedExpr, QualType DestType, + bool TakingAddress) { assert(OverloadedExpr->getType() == Context.OverloadTy); OverloadExpr::FindResult Ovl = OverloadExpr::find(OverloadedExpr); @@ -8707,10 +8725,11 @@ void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr, QualType DestType) { I != IEnd; ++I) { if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl()) ) { - NoteOverloadCandidate(FunTmpl->getTemplatedDecl(), DestType); + NoteOverloadCandidate(FunTmpl->getTemplatedDecl(), DestType, + TakingAddress); } else if (FunctionDecl *Fun = dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()) ) { - NoteOverloadCandidate(Fun, DestType); + NoteOverloadCandidate(Fun, DestType, TakingAddress); } } } @@ -10035,7 +10054,12 @@ private: Specialization = cast<FunctionDecl>(Specialization->getCanonicalDecl()); assert(S.isSameOrCompatibleFunctionType( Context.getCanonicalType(Specialization->getType()), - Context.getCanonicalType(TargetFunctionType))); + Context.getCanonicalType(TargetFunctionType)) || + (!S.getLangOpts().CPlusPlus && TargetType->isVoidPointerType())); + + if (!isFunctionAlwaysEnabled(S.Context, Specialization)) + return false; + Matches.push_back(std::make_pair(CurAccessFunPair, Specialization)); return true; } @@ -10066,13 +10090,17 @@ private: return false; } + if (!isFunctionAlwaysEnabled(S.Context, FunDecl)) + return false; + QualType ResultTy; if (Context.hasSameUnqualifiedType(TargetFunctionType, FunDecl->getType()) || S.IsNoReturnConversion(FunDecl->getType(), TargetFunctionType, - ResultTy)) { - Matches.push_back(std::make_pair(CurAccessFunPair, - cast<FunctionDecl>(FunDecl->getCanonicalDecl()))); + ResultTy) || + (!S.getLangOpts().CPlusPlus && TargetType->isVoidPointerType())) { + Matches.push_back(std::make_pair( + CurAccessFunPair, cast<FunctionDecl>(FunDecl->getCanonicalDecl()))); FoundNonTemplateFunction = true; return true; } @@ -10174,7 +10202,8 @@ public: << OvlExpr->getName() << TargetFunctionType << OvlExpr->getSourceRange(); if (FailedCandidates.empty()) - S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType); + S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType, + /*TakingAddress=*/true); else { // We have some deduction failure messages. Use them to diagnose // the function templates, and diagnose the non-template candidates @@ -10184,7 +10213,8 @@ public: I != IEnd; ++I) if (FunctionDecl *Fun = dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl())) - S.NoteOverloadCandidate(Fun, TargetFunctionType); + S.NoteOverloadCandidate(Fun, TargetFunctionType, + /*TakingAddress=*/true); FailedCandidates.NoteCandidates(S, OvlExpr->getLocStart()); } } @@ -10222,7 +10252,8 @@ public: S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_ambiguous) << OvlExpr->getName() << OvlExpr->getSourceRange(); - S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType); + S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType, + /*TakingAddress=*/true); } bool hadMultipleCandidates() const { return (OvlExpr->getNumDecls() > 1); } |