Skip to content

Commit 0b9a1be

Browse files
committed
Address post-review feedback/revert
#138731 (comment) A call expression might have been partially constructed, in which case it will be a call-expressions (and its type will not be that of a function) To address that, we check that the expression might already be a well-formed call
1 parent 0dff457 commit 0b9a1be

File tree

2 files changed

+68
-9
lines changed

2 files changed

+68
-9
lines changed

clang/lib/Sema/SemaExpr.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6551,12 +6551,25 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
65516551
}
65526552

65536553
// Any type that could be used to form a callable expression
6554-
static bool MayBeFunctionType(const ASTContext &Context, QualType T) {
6555-
return T == Context.BoundMemberTy || T == Context.UnknownAnyTy ||
6556-
T == Context.BuiltinFnTy || T == Context.OverloadTy ||
6557-
T->isFunctionType() || T->isFunctionReferenceType() ||
6558-
T->isMemberFunctionPointerType() || T->isFunctionPointerType() ||
6559-
T->isBlockPointerType() || T->isRecordType();
6554+
static bool MayBeFunctionType(const ASTContext &Context, const Expr* E) {
6555+
QualType T = E->getType();
6556+
if(T->isDependentType())
6557+
return true;
6558+
6559+
if( T == Context.BoundMemberTy || T == Context.UnknownAnyTy ||
6560+
T == Context.BuiltinFnTy || T == Context.OverloadTy ||
6561+
T->isFunctionType() || T->isFunctionReferenceType() ||
6562+
T->isMemberFunctionPointerType() || T->isFunctionPointerType() ||
6563+
T->isBlockPointerType() || T->isRecordType())
6564+
return true;
6565+
6566+
return isa<CallExpr,
6567+
DeclRefExpr,
6568+
MemberExpr,
6569+
CXXPseudoDestructorExpr,
6570+
OverloadExpr,
6571+
UnresolvedMemberExpr,
6572+
UnaryOperator>(E);
65606573
}
65616574

65626575
ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
@@ -6615,8 +6628,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
66156628
// If the type of the function itself is not dependent
66166629
// check that it is a reasonable as a function, as type deduction
66176630
// later assume the CallExpr has a sensible TYPE.
6618-
if (!Fn->getType()->isDependentType() &&
6619-
!MayBeFunctionType(Context, Fn->getType()))
6631+
if (!MayBeFunctionType(Context, Fn))
66206632
return ExprError(
66216633
Diag(LParenLoc, diag::err_typecheck_call_not_function)
66226634
<< Fn->getType() << Fn->getSourceRange());

clang/test/SemaTemplate/fun-template-def.cpp

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ T f1(T t1, U u1, int i1, T** tpp)
3333
i1 = t1[u1];
3434
i1 *= t1;
3535

36-
i1(u1, t1); // expected-error {{called object type 'int' is not a function or function pointer}}
36+
i1(u1, t1);
3737
u1(i1, t1);
3838

3939
U u2 = (T)i1;
@@ -108,4 +108,51 @@ auto k = c_<1>; // expected-note {{in instantiation of variable}}
108108

109109
}
110110

111+
namespace GH138731 {
112+
template <class...>
113+
using void_t = void;
114+
template <class...>
115+
using void_t = void;
116+
117+
template <class T>
118+
T&& declval();
119+
120+
struct S {
121+
S();
122+
static int f();
123+
static int var;
124+
};
125+
126+
namespace invoke_detail {
127+
128+
template <typename F>
129+
struct traits {
130+
template <typename... A>
131+
using result = decltype(declval<F>()(declval<A>()...));
132+
};
133+
134+
template <typename F, typename... A>
135+
using invoke_result_t = typename traits<F>::template result<A...>;
136+
137+
template <typename Void, typename F, typename... A>
138+
inline constexpr bool is_invocable_v = false;
139+
140+
template <typename F, typename... A>
141+
inline constexpr bool
142+
is_invocable_v<void_t<invoke_result_t<F, A...>>, F, A...> = true;
143+
144+
}
145+
146+
template <typename F, typename... A>
147+
inline constexpr bool is_invocable_v =
148+
invoke_detail::is_invocable_v<void, F, A...>;
149+
150+
static_assert(!is_invocable_v<int>);
151+
static_assert(!is_invocable_v<int, int>);
152+
static_assert(!is_invocable_v<S>);
153+
static_assert(is_invocable_v<decltype(&S::f)>);
154+
static_assert(!is_invocable_v<decltype(&S::var)>);
155+
156+
}
157+
111158
#endif

0 commit comments

Comments
 (0)