summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2016-05-11 17:43:13 +0000
committerReid Kleckner <rnk@google.com>2016-05-11 17:43:13 +0000
commit43be52a59f5333e31cadcdff8a6f1a77f5ba3cd3 (patch)
tree9e52be9f7f9e7bae46a8aa714f9f8dfa1f8e53d4
parent4e8c80382ff29c0e1dddfed5f497d9a1d7d36263 (diff)
downloadbcm5719-llvm-43be52a59f5333e31cadcdff8a6f1a77f5ba3cd3.tar.gz
bcm5719-llvm-43be52a59f5333e31cadcdff8a6f1a77f5ba3cd3.zip
Relax -Wcalling-convention-cast when casting to the default convention (cdecl)
llvm-svn: 269214
-rw-r--r--clang/lib/Sema/SemaCast.cpp10
-rw-r--r--clang/test/Sema/callingconv-cast.c9
2 files changed, 18 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index 646b884ce1a..1d95b1f9f18 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -1760,7 +1760,15 @@ static void DiagnoseCallingConvCast(Sema &Self, const ExprResult &SrcExpr,
if (!FD || !FD->hasBody(Definition))
return;
- // The source expression is a pointer to a known function defined in this TU.
+ // Only warn if we are casting from the default convention to a non-default
+ // convention. This can happen when the programmer forgot to apply the calling
+ // convention to the function definition and then inserted this cast to
+ // satisfy the type system.
+ CallingConv DefaultCC = Self.getASTContext().getDefaultCallingConvention(
+ FD->isVariadic(), FD->isCXXInstanceMember());
+ if (DstCC == DefaultCC || SrcCC != DefaultCC)
+ return;
+
// Diagnose this cast, as it is probably bad.
StringRef SrcCCName = FunctionType::getNameForCallConv(SrcCC);
StringRef DstCCName = FunctionType::getNameForCallConv(DstCC);
diff --git a/clang/test/Sema/callingconv-cast.c b/clang/test/Sema/callingconv-cast.c
index 9f1855baeb5..88b25e8f17a 100644
--- a/clang/test/Sema/callingconv-cast.c
+++ b/clang/test/Sema/callingconv-cast.c
@@ -21,6 +21,10 @@ void mismatched(int x) {}
typedef void (WINAPI *callback_t)(int);
void take_callback(callback_t callback);
+void WINAPI mismatched_stdcall(int x) {}
+
+void take_opaque_fn(void (*callback)(int));
+
int main() {
// expected-warning@+1 {{cast between incompatible calling conventions 'cdecl' and 'stdcall'}}
take_callback((callback_t)mismatched);
@@ -44,6 +48,11 @@ int main() {
// Another way to suppress the warning.
take_callback((callback_t)(void*)mismatched);
+
+ // Don't warn, because we're casting from stdcall to cdecl. Usually that means
+ // the programmer is rinsing the function pointer through some kind of opaque
+ // API.
+ take_opaque_fn((void (*)(int))mismatched_stdcall);
}
// MSFIXIT: fix-it:"{{.*}}callingconv-cast.c":{19:6-19:6}:"WINAPI "
OpenPOWER on IntegriCloud