aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaChecking.cpp16
-rw-r--r--test/SemaCXX/attr-format.cpp8
-rw-r--r--test/SemaCXX/vararg-non-pod.cpp18
3 files changed, 40 insertions, 2 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 81be8bfe8f..63c7bdd0cb 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/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<CXXMemberCallExpr>(TheCall);
+ bool IsMemberOperatorCall = isa<CXXOperatorCallExpr>(TheCall) &&
+ isa<CXXMethodDecl>(FDecl);
+ bool IsMemberFunction = isa<CXXMemberCallExpr>(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<CXXOperatorCallExpr>(TheCall) && isa<CXXMethodDecl>(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/test/SemaCXX/attr-format.cpp b/test/SemaCXX/attr-format.cpp
index da134a136d..3d5c3391c2 100644
--- a/test/SemaCXX/attr-format.cpp
+++ b/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/test/SemaCXX/vararg-non-pod.cpp b/test/SemaCXX/vararg-non-pod.cpp
index 86b560e814..da06d95718 100644
--- a/test/SemaCXX/vararg-non-pod.cpp
+++ b/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);
+ }
+}