Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,7 @@ Bug Fixes to C++ Support
- Fixed an assertion when trying to constant-fold various builtins when the argument
referred to a reference to an incomplete type. (#GH129397)
- Fixed a crash when a cast involved a parenthesized aggregate initialization in dependent context. (#GH72880)
- Fixed a crash when forming an invalid function type in a dependent context. (#GH138657) (#GH115725) (#GH68852)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
19 changes: 19 additions & 0 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6541,6 +6541,15 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
return Call;
}

// Any type that could be used to form a callable expression
static bool MayBeFunctionType(const ASTContext &Context, QualType T) {
return T == Context.BoundMemberTy || T == Context.UnknownAnyTy ||
T == Context.BuiltinFnTy || T == Context.OverloadTy ||
T->isFunctionType() || T->isFunctionReferenceType() ||
T->isMemberFunctionPointerType() || T->isFunctionPointerType() ||
T->isBlockPointerType() || T->isRecordType();
}

ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
MultiExprArg ArgExprs, SourceLocation RParenLoc,
Expr *ExecConfig, bool IsExecConfig,
Expand Down Expand Up @@ -6594,6 +6603,16 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
*this, dyn_cast<UnresolvedMemberExpr>(Fn->IgnoreParens()),
Fn->getBeginLoc());

if (!Fn->getType()->isDependentType()) {
// If the type of the function itself is not dependent
// check that it is a reasonable as a function, as type deduction
// later assume the CallExpr has a sensible TYPE.
if (!MayBeFunctionType(Context, Fn->getType()))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might suggest putting these in teh same 'if' to make it more obvious what is happening (or perhaps have MayBeFunctionType return true for a dependent type?

return ExprError(
Diag(LParenLoc, diag::err_typecheck_call_not_function)
<< Fn->getType() << Fn->getSourceRange());
}

return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy,
VK_PRValue, RParenLoc, CurFPFeatureOverrides());
}
Expand Down
51 changes: 50 additions & 1 deletion clang/test/SemaTemplate/fun-template-def.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s

// Tests that dependent expressions are always allowed, whereas non-dependent
// are checked as usual.
Expand Down Expand Up @@ -32,7 +33,7 @@ T f1(T t1, U u1, int i1, T** tpp)
i1 = t1[u1];
i1 *= t1;

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

U u2 = (T)i1;
Expand Down Expand Up @@ -60,3 +61,51 @@ void f3() {
f2<int*>(0);
f2<int>(0); // expected-error {{no matching function for call to 'f2'}}
}

#if __cplusplus >= 202002L
namespace GH138657 {
template <auto V> // #gh138657-template-head
class meta {};
template<int N>
class meta<N()> {}; // expected-error {{called object type 'int' is not a function or function point}}

template<int N[1]>
class meta<N()> {}; // expected-error {{called object type 'int *' is not a function or function point}}

template<char* N>
class meta<N()> {}; // expected-error {{called object type 'char *' is not a function or function point}}

struct S {};
template<S>
class meta<S()> {}; // expected-error {{template argument for non-type template parameter is treated as function type 'S ()'}}
// expected-note@#gh138657-template-head {{template parameter is declared here}}

}

namespace GH115725 {
template<auto ...> struct X {};
template<typename T, typename ...Ts> struct A {
template<Ts ...Ns, T *...Ps>
A(X<0(Ps)...>, Ts (*...qs)[Ns]);
// expected-error@-1{{called object type 'int' is not a function or function pointer}}

};
}

namespace GH68852 {
template <auto v>
struct constexpr_value {
template <class... Ts>
constexpr constexpr_value<v(Ts::value...)> call(Ts...) {
//expected-error@-1 {{called object type 'int' is not a function or function pointer}}
return {};
}
};

template <auto v> constexpr static inline auto c_ = constexpr_value<v>{};
// expected-note@-1 {{in instantiation of template}}
auto k = c_<1>; // expected-note {{in instantiation of variable}}

}

#endif
Loading