Skip to content

Commit 0c43b50

Browse files
committed
Address post-review feedback/revert
llvm#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 3f86287 commit 0c43b50

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
@@ -6542,12 +6542,25 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
65426542
}
65436543

65446544
// Any type that could be used to form a callable expression
6545-
static bool MayBeFunctionType(const ASTContext &Context, QualType T) {
6546-
return T == Context.BoundMemberTy || T == Context.UnknownAnyTy ||
6547-
T == Context.BuiltinFnTy || T == Context.OverloadTy ||
6548-
T->isFunctionType() || T->isFunctionReferenceType() ||
6549-
T->isMemberFunctionPointerType() || T->isFunctionPointerType() ||
6550-
T->isBlockPointerType() || T->isRecordType();
6545+
static bool MayBeFunctionType(const ASTContext &Context, const Expr* E) {
6546+
QualType T = E->getType();
6547+
if(T->isDependentType())
6548+
return true;
6549+
6550+
if( T == Context.BoundMemberTy || T == Context.UnknownAnyTy ||
6551+
T == Context.BuiltinFnTy || T == Context.OverloadTy ||
6552+
T->isFunctionType() || T->isFunctionReferenceType() ||
6553+
T->isMemberFunctionPointerType() || T->isFunctionPointerType() ||
6554+
T->isBlockPointerType() || T->isRecordType())
6555+
return true;
6556+
6557+
return isa<CallExpr,
6558+
DeclRefExpr,
6559+
MemberExpr,
6560+
CXXPseudoDestructorExpr,
6561+
OverloadExpr,
6562+
UnresolvedMemberExpr,
6563+
UnaryOperator>(E);
65516564
}
65526565

65536566
ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
@@ -6606,8 +6619,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
66066619
// If the type of the function itself is not dependent
66076620
// check that it is a reasonable as a function, as type deduction
66086621
// later assume the CallExpr has a sensible TYPE.
6609-
if (!Fn->getType()->isDependentType() &&
6610-
!MayBeFunctionType(Context, Fn->getType()))
6622+
if (!MayBeFunctionType(Context, Fn))
66116623
return ExprError(
66126624
Diag(LParenLoc, diag::err_typecheck_call_not_function)
66136625
<< 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)