Author: alexfh Date: Fri Feb 10 08:57:19 2017 New Revision: 294751 URL: http://llvm.org/viewvc/llvm-project?rev=294751&view=rev Log: [clang-tidy] Fix handling of function types in google-readability-casting
Modified: clang-tools-extra/trunk/clang-tidy/google/AvoidCStyleCastsCheck.cpp clang-tools-extra/trunk/test/clang-tidy/google-readability-casting.cpp Modified: clang-tools-extra/trunk/clang-tidy/google/AvoidCStyleCastsCheck.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/google/AvoidCStyleCastsCheck.cpp?rev=294751&r1=294750&r2=294751&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-tidy/google/AvoidCStyleCastsCheck.cpp (original) +++ clang-tools-extra/trunk/clang-tidy/google/AvoidCStyleCastsCheck.cpp Fri Feb 10 08:57:19 2017 @@ -73,14 +73,26 @@ void AvoidCStyleCastsCheck::check(const QualType SourceType = CastExpr->getSubExprAsWritten()->getType(); QualType DestType = CastExpr->getTypeAsWritten(); - if (SourceType == DestType) { + auto isFunction = [](QualType T) { + T = T.getCanonicalType().getNonReferenceType(); + return T->isFunctionType() || T->isFunctionPointerType() || + T->isMemberFunctionPointerType(); + }; + + bool FnToFnCast = isFunction(SourceType) && isFunction(DestType); + + // Function pointer/reference casts may be needed to resolve ambiguities in + // case of overloaded functions, so detection of redundant casts is trickier + // in this case. Don't emit "redundant cast" warnings for function + // pointer/reference types. + if (SourceType == DestType && !FnToFnCast) { diag(CastExpr->getLocStart(), "redundant cast to the same type") << FixItHint::CreateRemoval(ParenRange); return; } SourceType = SourceType.getCanonicalType(); DestType = DestType.getCanonicalType(); - if (SourceType == DestType) { + if (SourceType == DestType && !FnToFnCast) { diag(CastExpr->getLocStart(), "possibly redundant cast between typedefs of the same type"); return; @@ -111,27 +123,34 @@ void AvoidCStyleCastsCheck::check(const CastExpr->getRParenLoc().getLocWithOffset(-1)), SM, getLangOpts()); - auto diag_builder = + auto Diag = diag(CastExpr->getLocStart(), "C-style casts are discouraged; use %0"); auto ReplaceWithCast = [&](StringRef CastType) { - diag_builder << CastType; + Diag << CastType; const Expr *SubExpr = CastExpr->getSubExprAsWritten()->IgnoreImpCasts(); std::string CastText = (CastType + "<" + DestTypeString + ">").str(); if (!isa<ParenExpr>(SubExpr)) { CastText.push_back('('); - diag_builder << FixItHint::CreateInsertion( + Diag << FixItHint::CreateInsertion( Lexer::getLocForEndOfToken(SubExpr->getLocEnd(), 0, SM, getLangOpts()), ")"); } - diag_builder << FixItHint::CreateReplacement(ParenRange, CastText); + Diag << FixItHint::CreateReplacement(ParenRange, CastText); }; // Suggest appropriate C++ cast. See [expr.cast] for cast notation semantics. switch (CastExpr->getCastKind()) { + case CK_FunctionToPointerDecay: + ReplaceWithCast("static_cast"); + return; case CK_NoOp: + if (FnToFnCast) { + ReplaceWithCast("static_cast"); + return; + } if (needsConstCast(SourceType, DestType) && pointedTypesAreEqual(SourceType, DestType)) { ReplaceWithCast("const_cast"); @@ -166,7 +185,7 @@ void AvoidCStyleCastsCheck::check(const break; } - diag_builder << "static_cast/const_cast/reinterpret_cast"; + Diag << "static_cast/const_cast/reinterpret_cast"; } } // namespace readability Modified: clang-tools-extra/trunk/test/clang-tidy/google-readability-casting.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/google-readability-casting.cpp?rev=294751&r1=294750&r2=294751&view=diff ============================================================================== --- clang-tools-extra/trunk/test/clang-tidy/google-readability-casting.cpp (original) +++ clang-tools-extra/trunk/test/clang-tidy/google-readability-casting.cpp Fri Feb 10 08:57:19 2017 @@ -148,3 +148,77 @@ struct A { static const E ee = e; }; struct B : public A<E1> {}; + + +void overloaded_function(); +void overloaded_function(int); + +template<typename Fn> +void g(Fn fn) { + fn(); +} + +void function_casts() { + typedef void (*FnPtrVoid)(); + typedef void (&FnRefVoid)(); + typedef void (&FnRefInt)(int); + + g((void (*)())overloaded_function); + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [ + // CHECK-FIXES: g(static_cast<void (*)()>(overloaded_function)); + g((void (*)())&overloaded_function); + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [ + // CHECK-FIXES: g(static_cast<void (*)()>(&overloaded_function)); + g((void (&)())overloaded_function); + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [ + // CHECK-FIXES: g(static_cast<void (&)()>(overloaded_function)); + + g((FnPtrVoid)overloaded_function); + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [ + // CHECK-FIXES: g(static_cast<FnPtrVoid>(overloaded_function)); + g((FnPtrVoid)&overloaded_function); + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [ + // CHECK-FIXES: g(static_cast<FnPtrVoid>(&overloaded_function)); + g((FnRefVoid)overloaded_function); + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [ + // CHECK-FIXES: g(static_cast<FnRefVoid>(overloaded_function)); + + FnPtrVoid fn0 = (void (*)())&overloaded_function; + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [ + // CHECK-FIXES: FnPtrVoid fn0 = static_cast<void (*)()>(&overloaded_function); + FnPtrVoid fn1 = (void (*)())overloaded_function; + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [ + // CHECK-FIXES: FnPtrVoid fn1 = static_cast<void (*)()>(overloaded_function); + FnPtrVoid fn1a = (FnPtrVoid)overloaded_function; + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: C-style casts are discouraged; use static_cast [ + // CHECK-FIXES: FnPtrVoid fn1a = static_cast<FnPtrVoid>(overloaded_function); + FnRefInt fn2 = (void (&)(int))overloaded_function; + // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: C-style casts are discouraged; use static_cast [ + // CHECK-FIXES: FnRefInt fn2 = static_cast<void (&)(int)>(overloaded_function); + auto fn3 = (void (*)())&overloaded_function; + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [ + // CHECK-FIXES: auto fn3 = static_cast<void (*)()>(&overloaded_function); + auto fn4 = (void (*)())overloaded_function; + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [ + // CHECK-FIXES: auto fn4 = static_cast<void (*)()>(overloaded_function); + auto fn5 = (void (&)(int))overloaded_function; + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [ + // CHECK-FIXES: auto fn5 = static_cast<void (&)(int)>(overloaded_function); + + void (*fn6)() = (void (*)())&overloaded_function; + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [ + // CHECK-FIXES: void (*fn6)() = static_cast<void (*)()>(&overloaded_function); + void (*fn7)() = (void (*)())overloaded_function; + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [ + // CHECK-FIXES: void (*fn7)() = static_cast<void (*)()>(overloaded_function); + void (*fn8)() = (FnPtrVoid)overloaded_function; + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [ + // CHECK-FIXES: void (*fn8)() = static_cast<FnPtrVoid>(overloaded_function); + void (&fn9)(int) = (void (&)(int))overloaded_function; + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: C-style casts are discouraged; use static_cast [ + // CHECK-FIXES: void (&fn9)(int) = static_cast<void (&)(int)>(overloaded_function); + + void (*correct1)() = static_cast<void (*)()>(overloaded_function); + FnPtrVoid correct2 = static_cast<void (*)()>(&overloaded_function); + FnRefInt correct3 = static_cast<void (&)(int)>(overloaded_function); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits