summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaCast.cpp10
-rw-r--r--clang/lib/Sema/SemaExpr.cpp11
-rw-r--r--clang/lib/Sema/SemaInit.cpp4
-rw-r--r--clang/lib/Sema/SemaOverload.cpp57
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); }
OpenPOWER on IntegriCloud