[clang-tools-extra] r279507 - [clang-tidy] readability-non-const-parameter: add new check that warns when function parameters should be const
Daniel Marjamaki via cfe-commits
cfe-commits at lists.llvm.org
Tue Aug 23 03:09:08 PDT 2016
Author: danielmarjamaki
Date: Tue Aug 23 05:09:08 2016
New Revision: 279507
URL: http://llvm.org/viewvc/llvm-project?rev=279507&view=rev
Log:
[clang-tidy] readability-non-const-parameter: add new check that warns when function parameters should be const
The check will warn when the constness will make the function interface safer.
Reviewers: alexfh
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D15332
Added:
clang-tools-extra/trunk/clang-tidy/readability/NonConstParameterCheck.cpp
clang-tools-extra/trunk/clang-tidy/readability/NonConstParameterCheck.h
clang-tools-extra/trunk/docs/clang-tidy/checks/readability-non-const-parameter.rst
clang-tools-extra/trunk/test/clang-tidy/readability-non-const-parameter.cpp
Modified:
clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt
clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp
clang-tools-extra/trunk/docs/ReleaseNotes.rst
clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
Modified: clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt?rev=279507&r1=279506&r2=279507&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt Tue Aug 23 05:09:08 2016
@@ -12,6 +12,7 @@ add_clang_library(clangTidyReadabilityMo
InconsistentDeclarationParameterNameCheck.cpp
NamedParameterCheck.cpp
NamespaceCommentCheck.cpp
+ NonConstParameterCheck.cpp
ReadabilityTidyModule.cpp
RedundantControlFlowCheck.cpp
RedundantStringCStrCheck.cpp
Added: clang-tools-extra/trunk/clang-tidy/readability/NonConstParameterCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/NonConstParameterCheck.cpp?rev=279507&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/NonConstParameterCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/readability/NonConstParameterCheck.cpp Tue Aug 23 05:09:08 2016
@@ -0,0 +1,214 @@
+//===--- NonConstParameterCheck.cpp - clang-tidy---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "NonConstParameterCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+void NonConstParameterCheck::registerMatchers(MatchFinder *Finder) {
+ // Add parameters to Parameters.
+ Finder->addMatcher(parmVarDecl(unless(isInstantiated())).bind("Parm"), this);
+
+ // C++ constructor.
+ Finder->addMatcher(cxxConstructorDecl().bind("Ctor"), this);
+
+ // Track unused parameters, there is Wunused-parameter about unused
+ // parameters.
+ Finder->addMatcher(declRefExpr().bind("Ref"), this);
+
+ // Analyse parameter usage in function.
+ Finder->addMatcher(stmt(anyOf(unaryOperator(anyOf(hasOperatorName("++"),
+ hasOperatorName("--"))),
+ binaryOperator(), callExpr(), returnStmt(),
+ cxxConstructExpr()))
+ .bind("Mark"),
+ this);
+ Finder->addMatcher(varDecl(hasInitializer(anything())).bind("Mark"), this);
+}
+
+void NonConstParameterCheck::check(const MatchFinder::MatchResult &Result) {
+ if (const auto *Parm = Result.Nodes.getNodeAs<ParmVarDecl>("Parm")) {
+ if (const DeclContext *D = Parm->getParentFunctionOrMethod()) {
+ if (const auto *M = dyn_cast<CXXMethodDecl>(D)) {
+ if (M->isVirtual() || M->size_overridden_methods() != 0)
+ return;
+ }
+ }
+ addParm(Parm);
+ } else if (const auto *Ctor =
+ Result.Nodes.getNodeAs<CXXConstructorDecl>("Ctor")) {
+ for (const auto *Parm : Ctor->parameters())
+ addParm(Parm);
+ for (const auto *Init : Ctor->inits())
+ markCanNotBeConst(Init->getInit(), true);
+ } else if (const auto *Ref = Result.Nodes.getNodeAs<DeclRefExpr>("Ref")) {
+ setReferenced(Ref);
+ } else if (const auto *S = Result.Nodes.getNodeAs<Stmt>("Mark")) {
+ if (const auto *B = dyn_cast<BinaryOperator>(S)) {
+ if (B->isAssignmentOp())
+ markCanNotBeConst(B, false);
+ } else if (const auto *CE = dyn_cast<CallExpr>(S)) {
+ // Typically, if a parameter is const then it is fine to make the data
+ // const. But sometimes the data is written even though the parameter
+ // is const. Mark all data passed by address to the function.
+ for (const auto *Arg : CE->arguments()) {
+ markCanNotBeConst(Arg->IgnoreParenCasts(), true);
+ }
+
+ // Data passed by nonconst reference should not be made const.
+ if (const FunctionDecl *FD = CE->getDirectCallee()) {
+ unsigned ArgNr = 0U;
+ for (const auto *Par : FD->parameters()) {
+ if (ArgNr >= CE->getNumArgs())
+ break;
+ const Expr *Arg = CE->getArg(ArgNr++);
+ // Is this a non constant reference parameter?
+ const Type *ParType = Par->getType().getTypePtr();
+ if (!ParType->isReferenceType() || Par->getType().isConstQualified())
+ continue;
+ markCanNotBeConst(Arg->IgnoreParenCasts(), false);
+ }
+ }
+ } else if (const auto *CE = dyn_cast<CXXConstructExpr>(S)) {
+ for (const auto *Arg : CE->arguments()) {
+ markCanNotBeConst(Arg->IgnoreParenCasts(), true);
+ }
+ } else if (const auto *R = dyn_cast<ReturnStmt>(S)) {
+ markCanNotBeConst(R->getRetValue(), true);
+ } else if (const auto *U = dyn_cast<UnaryOperator>(S)) {
+ markCanNotBeConst(U, true);
+ }
+ } else if (const auto *VD = Result.Nodes.getNodeAs<VarDecl>("Mark")) {
+ const QualType T = VD->getType();
+ if ((T->isPointerType() && !T->getPointeeType().isConstQualified()) ||
+ T->isArrayType())
+ markCanNotBeConst(VD->getInit(), true);
+ }
+}
+
+void NonConstParameterCheck::addParm(const ParmVarDecl *Parm) {
+ // Only add nonconst integer/float pointer parameters.
+ const QualType T = Parm->getType();
+ if (!T->isPointerType() || T->getPointeeType().isConstQualified() ||
+ !(T->getPointeeType()->isIntegerType() ||
+ T->getPointeeType()->isFloatingType()))
+ return;
+
+ if (Parameters.find(Parm) != Parameters.end())
+ return;
+
+ ParmInfo PI;
+ PI.IsReferenced = false;
+ PI.CanBeConst = true;
+ Parameters[Parm] = PI;
+}
+
+void NonConstParameterCheck::setReferenced(const DeclRefExpr *Ref) {
+ auto It = Parameters.find(dyn_cast<ParmVarDecl>(Ref->getDecl()));
+ if (It != Parameters.end())
+ It->second.IsReferenced = true;
+}
+
+void NonConstParameterCheck::onEndOfTranslationUnit() {
+ diagnoseNonConstParameters();
+}
+
+void NonConstParameterCheck::diagnoseNonConstParameters() {
+ for (const auto &It : Parameters) {
+ const ParmVarDecl *Par = It.first;
+ const ParmInfo &ParamInfo = It.second;
+
+ // Unused parameter => there are other warnings about this.
+ if (!ParamInfo.IsReferenced)
+ continue;
+
+ // Parameter can't be const.
+ if (!ParamInfo.CanBeConst)
+ continue;
+
+ diag(Par->getLocation(), "pointer parameter '%0' can be pointer to const")
+ << Par->getName()
+ << FixItHint::CreateInsertion(Par->getLocStart(), "const ");
+ }
+}
+
+void NonConstParameterCheck::markCanNotBeConst(const Expr *E,
+ bool CanNotBeConst) {
+ if (!E)
+ return;
+
+ if (const auto *Cast = dyn_cast<ImplicitCastExpr>(E)) {
+ // If expression is const then ignore usage.
+ const QualType T = Cast->getType();
+ if (T->isPointerType() && T->getPointeeType().isConstQualified())
+ return;
+ }
+
+ E = E->IgnoreParenCasts();
+
+ if (const auto *B = dyn_cast<BinaryOperator>(E)) {
+ if (B->isAdditiveOp()) {
+ // p + 2
+ markCanNotBeConst(B->getLHS(), CanNotBeConst);
+ markCanNotBeConst(B->getRHS(), CanNotBeConst);
+ } else if (B->isAssignmentOp()) {
+ markCanNotBeConst(B->getLHS(), false);
+
+ // If LHS is not const then RHS can't be const.
+ const QualType T = B->getLHS()->getType();
+ if (T->isPointerType() && !T->getPointeeType().isConstQualified())
+ markCanNotBeConst(B->getRHS(), true);
+ }
+ } else if (const auto *C = dyn_cast<ConditionalOperator>(E)) {
+ markCanNotBeConst(C->getTrueExpr(), CanNotBeConst);
+ markCanNotBeConst(C->getFalseExpr(), CanNotBeConst);
+ } else if (const auto *U = dyn_cast<UnaryOperator>(E)) {
+ if (U->getOpcode() == UO_PreInc || U->getOpcode() == UO_PreDec ||
+ U->getOpcode() == UO_PostInc || U->getOpcode() == UO_PostDec) {
+ if (const auto *SubU =
+ dyn_cast<UnaryOperator>(U->getSubExpr()->IgnoreParenCasts()))
+ markCanNotBeConst(SubU->getSubExpr(), true);
+ markCanNotBeConst(U->getSubExpr(), CanNotBeConst);
+ } else if (U->getOpcode() == UO_Deref) {
+ if (!CanNotBeConst)
+ markCanNotBeConst(U->getSubExpr(), true);
+ } else {
+ markCanNotBeConst(U->getSubExpr(), CanNotBeConst);
+ }
+ } else if (const auto *A = dyn_cast<ArraySubscriptExpr>(E)) {
+ markCanNotBeConst(A->getBase(), true);
+ } else if (const auto *CLE = dyn_cast<CompoundLiteralExpr>(E)) {
+ markCanNotBeConst(CLE->getInitializer(), true);
+ } else if (const auto *Constr = dyn_cast<CXXConstructExpr>(E)) {
+ for (const auto *Arg : Constr->arguments()) {
+ if (const auto *M = dyn_cast<MaterializeTemporaryExpr>(Arg))
+ markCanNotBeConst(cast<Expr>(M->getTemporary()), CanNotBeConst);
+ }
+ } else if (const auto *ILE = dyn_cast<InitListExpr>(E)) {
+ for (unsigned I = 0U; I < ILE->getNumInits(); ++I)
+ markCanNotBeConst(ILE->getInit(I), true);
+ } else if (CanNotBeConst) {
+ // Referencing parameter.
+ if (const auto *D = dyn_cast<DeclRefExpr>(E)) {
+ auto It = Parameters.find(dyn_cast<ParmVarDecl>(D->getDecl()));
+ if (It != Parameters.end())
+ It->second.CanBeConst = false;
+ }
+ }
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
Added: clang-tools-extra/trunk/clang-tidy/readability/NonConstParameterCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/NonConstParameterCheck.h?rev=279507&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/NonConstParameterCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/readability/NonConstParameterCheck.h Tue Aug 23 05:09:08 2016
@@ -0,0 +1,64 @@
+//===--- NonConstParameterCheck.h - clang-tidy-------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_NON_CONST_PARAMETER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_NON_CONST_PARAMETER_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Warn when a pointer function parameter can be const.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-non-const-parameter.html
+class NonConstParameterCheck : public ClangTidyCheck {
+public:
+ NonConstParameterCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+ void onEndOfTranslationUnit() override;
+
+private:
+ /// Parameter info.
+ struct ParmInfo {
+ /// Is function parameter referenced?
+ bool IsReferenced;
+
+ /// Can function parameter be const?
+ bool CanBeConst;
+ };
+
+ /// Track all nonconst integer/float parameters.
+ std::map<const ParmVarDecl *, ParmInfo> Parameters;
+
+ /// Add function parameter.
+ void addParm(const ParmVarDecl *Parm);
+
+ /// Set IsReferenced.
+ void setReferenced(const DeclRefExpr *Ref);
+
+ /// Set CanNotBeConst.
+ /// Visits sub expressions recursively. If a DeclRefExpr is found
+ /// and CanNotBeConst is true the Parameter is marked as not-const.
+ /// The CanNotBeConst is updated as sub expressions are visited.
+ void markCanNotBeConst(const Expr *E, bool CanNotBeConst);
+
+ /// Diagnose non const parameters.
+ void diagnoseNonConstParameters();
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_NON_CONST_PARAMETER_H
Modified: clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp?rev=279507&r1=279506&r2=279507&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp Tue Aug 23 05:09:08 2016
@@ -20,6 +20,7 @@
#include "ImplicitBoolCastCheck.h"
#include "InconsistentDeclarationParameterNameCheck.h"
#include "NamedParameterCheck.h"
+#include "NonConstParameterCheck.h"
#include "RedundantControlFlowCheck.h"
#include "RedundantSmartptrGetCheck.h"
#include "RedundantStringCStrCheck.h"
@@ -57,6 +58,8 @@ public:
"readability-static-definition-in-anonymous-namespace");
CheckFactories.registerCheck<readability::NamedParameterCheck>(
"readability-named-parameter");
+ CheckFactories.registerCheck<NonConstParameterCheck>(
+ "readability-non-const-parameter");
CheckFactories.registerCheck<RedundantControlFlowCheck>(
"readability-redundant-control-flow");
CheckFactories.registerCheck<RedundantSmartptrGetCheck>(
Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=279507&r1=279506&r2=279507&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Tue Aug 23 05:09:08 2016
@@ -85,6 +85,12 @@ Improvements to clang-tidy
Warns about the performance overhead arising from concatenating strings using
the ``operator+``, instead of ``operator+=``.
+- New `readability-non-const-parameter
+ <http://clang.llvm.org/extra/clang-tidy/checks/readability-non-const-parameter.html>`_ check
+
+ Flags function parameters of a pointer type that could be changed to point to
+ a constant type instead.
+
Improvements to include-fixer
-----------------------------
Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=279507&r1=279506&r2=279507&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Tue Aug 23 05:09:08 2016
@@ -128,6 +128,7 @@ Clang-Tidy Checks
readability-implicit-bool-cast
readability-inconsistent-declaration-parameter-name
readability-named-parameter
+ readability-non-const-parameter
readability-redundant-control-flow
readability-redundant-smartptr-get
readability-redundant-string-cstr
Added: clang-tools-extra/trunk/docs/clang-tidy/checks/readability-non-const-parameter.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/readability-non-const-parameter.rst?rev=279507&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/readability-non-const-parameter.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/readability-non-const-parameter.rst Tue Aug 23 05:09:08 2016
@@ -0,0 +1,44 @@
+.. title:: clang-tidy - readability-non-const-parameter
+
+readability-non-const-parameter
+===============================
+
+The check finds function parameters of a pointer type that could be changed to
+point to a constant type instead.
+
+When const is used properly, many mistakes can be avoided. Advantages when using
+const properly:
+ * prevent unintentional modification of data
+ * get additional warnings such as using uninitialized data
+ * make it easier for developers to see possible side effects
+
+This check is not strict about constness, it only warns when the constness will
+make the function interface safer.
+
+.. code:: c++
+
+ // warning here; the declaration "const char *p" would make the function
+ // interface safer.
+ char f1(char *p) {
+ return *p;
+ }
+
+ // no warning; the declaration could be more const "const int * const p" but
+ // that does not make the function interface safer.
+ int f2(const int *p) {
+ return *p;
+ }
+
+ // no warning; making x const does not make the function interface safer
+ int f3(int x) {
+ return x;
+ }
+
+ // no warning; Technically, *p can be const ("const struct S *p"). But making
+ // *p const could be misleading. People might think that it's safe to pass
+ // const data to this function.
+ struct S { int *a; int *b; };
+ int f3(struct S *p) {
+ *(p->a) = 0;
+ }
+
Added: clang-tools-extra/trunk/test/clang-tidy/readability-non-const-parameter.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/readability-non-const-parameter.cpp?rev=279507&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/readability-non-const-parameter.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/readability-non-const-parameter.cpp Tue Aug 23 05:09:08 2016
@@ -0,0 +1,279 @@
+// RUN: %check_clang_tidy %s readability-non-const-parameter %t
+
+// Currently the checker only warns about pointer arguments.
+//
+// It can be defined both that the data is const and that the pointer is const,
+// the checker only checks if the data can be const-specified.
+//
+// It does not warn about pointers to records or function pointers.
+
+// Some external function where first argument is nonconst and second is const.
+char *strcpy1(char *dest, const char *src);
+unsigned my_strcpy(char *buf, const char *s);
+unsigned my_strlen(const char *buf);
+
+// CHECK-MESSAGES: :[[@LINE+1]]:29: warning: pointer parameter 'last' can be pointer to const [readability-non-const-parameter]
+void warn1(int *first, int *last) {
+ // CHECK-FIXES: {{^}}void warn1(int *first, const int *last) {{{$}}
+ *first = 0;
+ if (first < last) {
+ } // <- last can be const
+}
+
+// TODO: warning should be written here
+void warn2(char *p) {
+ char buf[10];
+ strcpy1(buf, p);
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:19: warning: pointer parameter 'p' can be
+void assign1(int *p) {
+ // CHECK-FIXES: {{^}}void assign1(const int *p) {{{$}}
+ const int *q;
+ q = p;
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:19: warning: pointer parameter 'p' can be
+void assign2(int *p) {
+ // CHECK-FIXES: {{^}}void assign2(const int *p) {{{$}}
+ const int *q;
+ q = p + 1;
+}
+
+void assign3(int *p) {
+ *p = 0;
+}
+
+void assign4(int *p) {
+ *p += 2;
+}
+
+void assign5(char *p) {
+ p[0] = 0;
+}
+
+void assign6(int *p) {
+ int *q;
+ q = p++;
+}
+
+void assign7(char *p) {
+ char *a, *b;
+ a = b = p;
+}
+
+void assign8(char *a, char *b) {
+ char *x;
+ x = (a ? a : b);
+}
+
+void assign9(unsigned char *str, const unsigned int i) {
+ unsigned char *p;
+ for (p = str + i; *p;) {
+ }
+}
+
+void assign10(int *buf) {
+ int i, *p;
+ for (i = 0, p = buf; i < 10; i++, p++) {
+ *p = 1;
+ }
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:17: warning: pointer parameter 'p' can be
+void init1(int *p) {
+ // CHECK-FIXES: {{^}}void init1(const int *p) {{{$}}
+ const int *q = p;
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:17: warning: pointer parameter 'p' can be
+void init2(int *p) {
+ // CHECK-FIXES: {{^}}void init2(const int *p) {{{$}}
+ const int *q = p + 1;
+}
+
+void init3(int *p) {
+ int *q = p;
+}
+
+void init4(float *p) {
+ int *q = (int *)p;
+}
+
+void init5(int *p) {
+ int *i = p ? p : 0;
+}
+
+void init6(int *p) {
+ int *a[] = {p, p, 0};
+}
+
+void init7(int *p, int x) {
+ for (int *q = p + x - 1; 0; q++)
+ ;
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:18: warning: pointer parameter 'p' can be
+int return1(int *p) {
+ // CHECK-FIXES: {{^}}int return1(const int *p) {{{$}}
+ return *p;
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:25: warning: pointer parameter 'p' can be
+const int *return2(int *p) {
+ // CHECK-FIXES: {{^}}const int *return2(const int *p) {{{$}}
+ return p;
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:25: warning: pointer parameter 'p' can be
+const int *return3(int *p) {
+ // CHECK-FIXES: {{^}}const int *return3(const int *p) {{{$}}
+ return p + 1;
+}
+
+// CHECK-MESSAGES: :[[@LINE+1]]:27: warning: pointer parameter 'p' can be
+const char *return4(char *p) {
+ // CHECK-FIXES: {{^}}const char *return4(const char *p) {{{$}}
+ return p ? p : "";
+}
+
+char *return5(char *s) {
+ return s;
+}
+
+char *return6(char *s) {
+ return s + 1;
+}
+
+char *return7(char *a, char *b) {
+ return a ? a : b;
+}
+
+char return8(int *p) {
+ return ++(*p);
+}
+
+void dontwarn1(int *p) {
+ ++(*p);
+}
+
+void dontwarn2(int *p) {
+ (*p)++;
+}
+
+int dontwarn3(_Atomic(int) * p) {
+ return *p;
+}
+
+void callFunction1(char *p) {
+ strcpy1(p, "abc");
+}
+
+void callFunction2(char *p) {
+ strcpy1(&p[0], "abc");
+}
+
+void callFunction3(char *p) {
+ strcpy1(p + 2, "abc");
+}
+
+char *callFunction4(char *p) {
+ return strcpy1(p, "abc");
+}
+
+unsigned callFunction5(char *buf) {
+ unsigned len = my_strlen(buf);
+ return len + my_strcpy(buf, "abc");
+}
+
+void f6(int **p);
+void callFunction6(int *p) { f6(&p); }
+
+typedef union { void *v; } t;
+void f7(t obj);
+void callFunction7(int *p) {
+ f7((t){p});
+}
+
+void f8(int &x);
+void callFunction8(int *p) {
+ f8(*p);
+}
+
+// Don't warn about nonconst function pointers that can be const.
+void functionpointer(double f(double), int x) {
+ f(x);
+}
+
+// TODO: This is a false positive.
+// CHECK-MESSAGES: :[[@LINE+1]]:27: warning: pointer parameter 'p' can be
+int functionpointer2(int *p) {
+ return *p;
+}
+void use_functionpointer2() {
+ int (*fp)(int *) = functionpointer2; // <- the parameter 'p' can't be const
+}
+
+// Don't warn about nonconst record pointers that can be const.
+struct XY {
+ int *x;
+ int *y;
+};
+void recordpointer(struct XY *xy) {
+ *(xy->x) = 0;
+}
+
+class C {
+public:
+ C(int *p) : p(p) {}
+
+private:
+ int *p;
+};
+
+class C2 {
+public:
+ // CHECK-MESSAGES: :[[@LINE+1]]:11: warning: pointer parameter 'p' can be
+ C2(int *p) : p(p) {}
+ // CHECK-FIXES: {{^}} C2(const int *p) : p(p) {}{{$}}
+
+private:
+ const int *p;
+};
+
+void tempObject(int *p) {
+ C c(p);
+}
+
+// avoid fp for const pointer array
+void constPointerArray(const char *remapped[][2]) {
+ const char *name = remapped[0][0];
+}
+
+class Warn {
+public:
+ // CHECK-MESSAGES: :[[@LINE+1]]:21: warning: pointer parameter 'p' can be
+ void doStuff(int *p) {
+ // CHECK-FIXES: {{^}} void doStuff(const int *p) {{{$}}
+ x = *p;
+ }
+
+private:
+ int x;
+};
+
+class Base {
+public:
+ // Ensure there is no false positive for this method. It is virtual.
+ virtual void doStuff(int *p) {
+ int x = *p;
+ }
+};
+
+class Derived : public Base {
+public:
+ // Ensure there is no false positive for this method. It overrides a method.
+ void doStuff(int *p) override {
+ int x = *p;
+ }
+};
More information about the cfe-commits
mailing list