From 726d11c41b99e7e2b54547dfade6d327adaac79f Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Thu, 11 Oct 2012 00:30:58 +0000 Subject: [PATCH] Make sure we perform the variadic method check correctly for calls to a member operator(). PR14057. llvm-svn: 165678 --- clang/lib/Sema/SemaChecking.cpp | 16 ++++++++++++++-- clang/test/SemaCXX/attr-format.cpp | 8 ++++++++ clang/test/SemaCXX/vararg-non-pod.cpp | 18 ++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 81be8bf..63c7bdd 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -542,11 +542,23 @@ void Sema::CheckConstructorCall(FunctionDecl *FDecl, Expr **Args, /// and safety properties not strictly enforced by the C type system. bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, const FunctionProtoType *Proto) { - bool IsMemberFunction = isa(TheCall); + bool IsMemberOperatorCall = isa(TheCall) && + isa(FDecl); + bool IsMemberFunction = isa(TheCall) || + IsMemberOperatorCall; VariadicCallType CallType = getVariadicCallType(FDecl, Proto, TheCall->getCallee()); unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0; - checkCall(FDecl, TheCall->getArgs(), TheCall->getNumArgs(), NumProtoArgs, + Expr** Args = TheCall->getArgs(); + unsigned NumArgs = TheCall->getNumArgs(); + if (isa(TheCall) && isa(FDecl)) { + // If this is a call to a member operator, hide the first argument + // from checkCall. + // FIXME: Our choice of AST representation here is less than ideal. + ++Args; + --NumArgs; + } + checkCall(FDecl, Args, NumArgs, NumProtoArgs, IsMemberFunction, TheCall->getRParenLoc(), TheCall->getCallee()->getSourceRange(), CallType); diff --git a/clang/test/SemaCXX/attr-format.cpp b/clang/test/SemaCXX/attr-format.cpp index da134a1..3d5c339 100644 --- a/clang/test/SemaCXX/attr-format.cpp +++ b/clang/test/SemaCXX/attr-format.cpp @@ -14,6 +14,8 @@ struct S { expected-error{{out of bounds}} const char* h3(const char*) __attribute__((format_arg(1))); // \ expected-error{{invalid for the implicit this argument}} + + void operator() (const char*, ...) __attribute__((format(printf, 2, 3))); }; // PR5521 @@ -33,3 +35,9 @@ namespace PR8625 { s.f(str, "%s", str); } } + +// Make sure we interpret member operator calls as having an implicit +// this argument. +void test_operator_call(S s, const char* str) { + s("%s", str); +} diff --git a/clang/test/SemaCXX/vararg-non-pod.cpp b/clang/test/SemaCXX/vararg-non-pod.cpp index 86b560e..da06d95 100644 --- a/clang/test/SemaCXX/vararg-non-pod.cpp +++ b/clang/test/SemaCXX/vararg-non-pod.cpp @@ -123,3 +123,21 @@ int t9(int n) { // Make sure the error works in potentially-evaluated sizeof return (int)sizeof(*(Helper(Foo()), (int (*)[n])0)); // expected-warning{{cannot pass object of non-POD type}} } + +// PR14057 +namespace t10 { + struct F { + F(); + }; + + struct S { + void operator()(F, ...); + }; + + void foo() { + S s; + F f; + s.operator()(f); + s(f); + } +} -- 2.7.4