]> granicus.if.org Git - clang/commitdiff
Extend -Wcast-calling-convention to warn on declarations as well as definitions
authorReid Kleckner <rnk@google.com>
Tue, 31 Jan 2017 19:37:45 +0000 (19:37 +0000)
committerReid Kleckner <rnk@google.com>
Tue, 31 Jan 2017 19:37:45 +0000 (19:37 +0000)
My original warning was very conservative and I never revisited the
heuristics that were used.

This would have caught http://crbug.com/687251 at compile time.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@293677 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaCast.cpp
test/Sema/callingconv-cast.c

index 6222e4cec47a04720ac3794797e99695cbc2867f..6f9852aaf535f0c7436f81af5cd952b91a018752 100644 (file)
@@ -1763,13 +1763,12 @@ static void DiagnoseCallingConvCast(Sema &Self, const ExprResult &SrcExpr,
   if (!DRE)
     return;
   auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl());
-  const FunctionDecl *Definition;
-  if (!FD || !FD->hasBody(Definition))
+  if (!FD)
     return;
 
   // 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
+  // convention to the function declaration and then inserted this cast to
   // satisfy the type system.
   CallingConv DefaultCC = Self.getASTContext().getDefaultCallingConvention(
       FD->isVariadic(), FD->isCXXInstanceMember());
@@ -1792,7 +1791,7 @@ static void DiagnoseCallingConvCast(Sema &Self, const ExprResult &SrcExpr,
   // whose address was taken. Try to use the latest macro for the convention.
   // For example, users probably want to write "WINAPI" instead of "__stdcall"
   // to match the Windows header declarations.
-  SourceLocation NameLoc = Definition->getNameInfo().getLoc();
+  SourceLocation NameLoc = FD->getFirstDecl()->getNameInfo().getLoc();
   Preprocessor &PP = Self.getPreprocessor();
   SmallVector<TokenValue, 6> AttrTokens;
   SmallString<64> CCAttrText;
index 12c0dcbc256acf00aa2f00311366480c8f3374e0..599a7d1e66d7da9ceee0d2fe0ec3e53878143244 100644 (file)
@@ -15,6 +15,13 @@ void mismatched_before_winapi(int x) {}
 // expected-note@+1 3 {{consider defining 'mismatched' with the 'stdcall' calling convention}}
 void mismatched(int x) {}
 
+// expected-note@+1 {{consider defining 'mismatched_declaration' with the 'stdcall' calling convention}}
+void mismatched_declaration(int x);
+
+// expected-note@+1 {{consider defining 'suggest_fix_first_redecl' with the 'stdcall' calling convention}}
+void suggest_fix_first_redecl(int x);
+void suggest_fix_first_redecl(int x);
+
 typedef void (WINAPI *callback_t)(int);
 void take_callback(callback_t callback);
 
@@ -46,6 +53,12 @@ int main() {
   // Another way to suppress the warning.
   take_callback((callback_t)(void*)mismatched);
 
+  // Warn on declarations as well as definitions.
+  // expected-warning@+1 {{cast between incompatible calling conventions 'cdecl' and 'stdcall'}}
+  take_callback((callback_t)mismatched_declaration);
+  // expected-warning@+1 {{cast between incompatible calling conventions 'cdecl' and 'stdcall'}}
+  take_callback((callback_t)suggest_fix_first_redecl);
+
   // 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.