File indexing completed on 2024-04-28 16:57:54

0001 /*
0002     This file is part of the clazy static checker.
0003 
0004      Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
0005      Author: SĂ©rgio Martins <sergio.martins@kdab.com>
0006 
0007      Copyright (C) 2015-2016 Sergio Martins <smartins@kde.org>
0008 
0009      This library is free software; you can redistribute it and/or
0010      modify it under the terms of the GNU Library General Public
0011      License as published by the Free Software Foundation; either
0012      version 2 of the License, or (at your option) any later version.
0013 
0014      This library is distributed in the hope that it will be useful,
0015      but WITHOUT ANY WARRANTY; without even the implied warranty of
0016      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0017      Library General Public License for more details.
0018 
0019      You should have received a copy of the GNU Library General Public License
0020      along with this library; see the file COPYING.LIB.  If not, write to
0021      the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0022      Boston, MA 02110-1301, USA.
0023  */
0024 
0025 #ifndef MOREWARNINGS_UTILS_H
0026 #define MOREWARNINGS_UTILS_H
0027 
0028 #include "SourceCompatibilityHelpers.h"
0029 
0030 #include <clang/Basic/SourceManager.h>
0031 #include <clang/AST/DeclCXX.h>
0032 #include <clang/AST/Expr.h>
0033 #include <clang/AST/ExprCXX.h>
0034 #include <clang/AST/Stmt.h>
0035 #include <clang/AST/DeclTemplate.h>
0036 #include <clang/Basic/SourceLocation.h>
0037 #include <llvm/ADT/ArrayRef.h>
0038 #include <llvm/ADT/StringRef.h>
0039 #include <llvm/Config/llvm-config.h>
0040 
0041 #include <string>
0042 #include <vector>
0043 #include <map>
0044 
0045 // TODO: this is a dumping ground, most of these functions should be moved to the other *Utils classes
0046 
0047 namespace clang {
0048 class CXXNamedCastExpr;
0049 class CXXRecordDecl;
0050 class CXXMemberCallExpr;
0051 class CXXConstructExpr;
0052 class CompilerInstance;
0053 class ClassTemplateSpecializationDecl;
0054 class Decl;
0055 class ParentMap;
0056 class SourceManager;
0057 class Stmt;
0058 class SourceLocation;
0059 class ExprWithCleanups;
0060 class ValueDecl;
0061 class ConditionalOperator;
0062 class CXXMethodDecl;
0063 class BinaryOperator;
0064 class CXXOperatorCallExpr;
0065 class CallExpr;
0066 class DeclStmt;
0067 class Expr;
0068 class FunctionDecl;
0069 class LangOptions;
0070 class ParmVarDecl;
0071 class StringLiteral;
0072 class UserDefinedLiteral;
0073 class VarDecl;
0074 }
0075 
0076 struct StmtBodyRange;
0077 
0078 namespace Utils {
0079 /// Returns true if the class has at least one constexpr ctor
0080 bool hasConstexprCtor(clang::CXXRecordDecl *decl);
0081 
0082 /// Returns the type we're casting *from*
0083 clang::CXXRecordDecl * namedCastInnerDecl(clang::CXXNamedCastExpr *staticOrDynamicCast);
0084 
0085 /// Returns the type we're casting *to*
0086 clang::CXXRecordDecl * namedCastOuterDecl(clang::CXXNamedCastExpr *staticOrDynamicCast);
0087 
0088 /// Returns the class declaration from a variable declaration
0089 // So, if the var decl is "Foo f"; it returns the declaration of Foo
0090 clang::CXXRecordDecl * recordFromVarDecl(clang::Decl *);
0091 
0092 /// Returns the template specialization from a variable declaration
0093 // So, if the var decl is "QList<Foo> f;", returns the template specialization QList<Foo>
0094 clang::ClassTemplateSpecializationDecl * templateSpecializationFromVarDecl(clang::Decl *);
0095 
0096 /// Returns true if all the child member function calls are const functions.
0097 bool allChildrenMemberCallsConst(clang::Stmt *stm);
0098 
0099 /// Returns true if at least a UnaryOperator, BinaryOperator or non-const function call is found
0100 bool childsHaveSideEffects(clang::Stmt *stm);
0101 
0102 /// Receives a member call, such as "list.reserve()" and returns the declaration of the variable list
0103 // such as "QList<F> list"
0104 clang::ValueDecl * valueDeclForMemberCall(clang::CXXMemberCallExpr *);
0105 
0106 /// Receives an operator call, such as "list << fooo" and returns the declaration of the variable list
0107 // such as "QList<F> list"
0108 clang::ValueDecl * valueDeclForOperatorCall(clang::CXXOperatorCallExpr *);
0109 
0110 // overload
0111 clang::ValueDecl * valueDeclForCallExpr(clang::CallExpr *);
0112 
0113 // Returns true of this value decl is a member variable of a class or struct
0114 // returns null if not
0115 clang::CXXRecordDecl* isMemberVariable(clang::ValueDecl *);
0116 
0117 // Returns true if a body of statements contains a non const member call on object declared by varDecl
0118 // For example:
0119 // Foo foo; // this is the varDecl
0120 // while (bar) { foo.setValue(); // non-const call }
0121 bool containsNonConstMemberCall(clang::ParentMap *map, clang::Stmt *body, const clang::VarDecl *varDecl);
0122 
0123 // Returns true if there's an assignment to varDecl in body
0124 // Example: our_var = something_else
0125 bool isAssignedFrom(clang::Stmt *body, const clang::VarDecl *varDecl);
0126 
0127 // Returns true if varDecl is assigned to something
0128 // Example: something_else = our_var
0129 bool isAssignedTo(clang::Stmt *body, const clang::VarDecl *varDecl);
0130 
0131 // Returns whether the variable is returned in body
0132 bool isReturned(clang::Stmt *body, const clang::VarDecl *varDecl);
0133 
0134 // Returns true if a body of statements contains a function call that takes our variable (varDecl)
0135 // By ref or pointer
0136 bool isPassedToFunction(const StmtBodyRange &bodyRange, const clang::VarDecl *varDecl,
0137                         bool byRefOrPtrOnly);
0138 
0139 // Returns true if we take the address of varDecl, such as: &foo
0140 bool addressIsTaken(const clang::CompilerInstance &ci, clang::Stmt *body,
0141                     const clang::ValueDecl *valDecl);
0142 
0143 // QString::fromLatin1("foo")    -> true
0144 // QString::fromLatin1("foo", 1) -> false
0145 bool callHasDefaultArguments(clang::CallExpr *expr);
0146 
0147 // If there's a child of type StringLiteral, returns true
0148 // if allowEmpty is false, "" will be ignored
0149 bool containsStringLiteral(clang::Stmt *, bool allowEmpty = true, int depth = -1);
0150 
0151 bool isInsideOperatorCall(clang::ParentMap *map, clang::Stmt *s,
0152                           const std::vector<llvm::StringRef> &anyOf);
0153 
0154 bool insideCTORCall(clang::ParentMap *map, clang::Stmt *s,
0155                     const std::vector<llvm::StringRef> &anyOf);
0156 
0157 // returns true if the ternary operator has two string literal arguments, such as:
0158 // foo ? "bar" : "baz"
0159 bool ternaryOperatorIsOfStringLiteral(clang::ConditionalOperator*);
0160 
0161 bool isAssignOperator(clang::CXXOperatorCallExpr *op,
0162                       llvm::StringRef className,
0163                       llvm::StringRef argumentType, const clang::LangOptions &lo);
0164 
0165 bool isImplicitCastTo(clang::Stmt *, const std::string &);
0166 
0167 bool presumedLocationsEqual(const clang::PresumedLoc &l1, const clang::PresumedLoc &l2);
0168 
0169 
0170 // Returns the list of methods with name methodName that the class/struct record contains
0171 std::vector<clang::CXXMethodDecl*> methodsFromString(const clang::CXXRecordDecl *record,
0172                                                      const std::string &methodName);
0173 
0174 // Returns the most derived class. (CXXMemberCallExpr::getRecordDecl() return the first base class with the method)
0175 // The returned callee is the name of the variable on which the member call was made:
0176 // o1->foo() => "o1"
0177 // foo() => "this"
0178 const clang::CXXRecordDecl* recordForMemberCall(clang::CXXMemberCallExpr *call,
0179                                                 std::string &implicitCallee);
0180 
0181 bool isAscii(clang::StringLiteral *lt);
0182 
0183 // Checks if Statement s inside an operator* call
0184 bool isInDerefExpression(clang::Stmt *s, clang::ParentMap *map);
0185 
0186 // For a a chain called expression like foo().bar().baz() returns a list of calls
0187 // {baz(), bar(), foo()}
0188 
0189 // the parameter lastCallExpr to pass would be baz()
0190 // No need to specify the other callexprs, they are children of the first one, since the AST looks like:
0191 // - baz
0192 // -- bar
0193 // --- foo
0194 std::vector<clang::CallExpr *> callListForChain(clang::CallExpr *lastCallExpr);
0195 
0196 // Returns the first base class
0197 clang::CXXRecordDecl * rootBaseClass(clang::CXXRecordDecl *derived);
0198 
0199 // Returns the copy ctor for this class
0200 clang::CXXConstructorDecl *copyCtor(const clang::CXXRecordDecl *);
0201 
0202 // Returns the copy-assignment operator for this class
0203 clang::CXXMethodDecl *copyAssign(const clang::CXXRecordDecl *);
0204 
0205 bool hasMember(clang::CXXRecordDecl *record, const std::string &memberTypeName);
0206 
0207 /**
0208  * Returns true if record is a shared pointer (boost, Qt or stl only).
0209  */
0210 bool isSharedPointer(clang::CXXRecordDecl *record);
0211 
0212 /**
0213  * Returns true if varDecl is initialized externally.
0214  * Example:
0215  *     QList<Foo> list = getList(); // true
0216  *     QList<int> list = list2;     // true
0217  *     QList<int> list = {1, 2, 3}; // false
0218  *     QList<int> list;             // false
0219  */
0220 bool isInitializedExternally(clang::VarDecl *varDecl);
0221 
0222 /**
0223  * Returns true if declStmt refers to varDecl
0224  */
0225 bool referencesVarDecl(clang::DeclStmt *declStmt, clang::VarDecl *varDecl);
0226 
0227 /**
0228  * Returns true if the body of a function is empty.
0229  * Returns false if either function or it's body are null.
0230  */
0231 bool functionHasEmptyBody(clang::FunctionDecl *func);
0232 
0233 /**
0234  * If stm is an UnaryOperator or BinaryOperator that writes to the variable it returns the expression
0235  * that represents the variable (Usually a MemberExpr or DeclRefExpr for local variables).
0236  *
0237  * Otherwise returns nullptr.
0238  *
0239  * The operators that write to the variable are operator=, operator+=, operator++, etc.
0240  */
0241 clang::Expr* isWriteOperator(clang::Stmt *stm);
0242 
0243 /**
0244  * Gets the UserDefinedLiteral of type @p type which is somewhere in the ast of @p stm.
0245  * Returns nullptr if there's no such UserDefinedLiteral.
0246  */
0247 clang::UserDefinedLiteral* userDefinedLiteral(clang::Stmt *stm, const std::string &type,
0248                                               const clang::LangOptions &lo);
0249 
0250 /**
0251  * Returns the function parameters fom @p func
0252  * This should be used instead of calling FunctionDecl::params() since it changed signature in
0253  * clang 3.9.
0254  */
0255 #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR <= 8
0256 clang::FunctionDecl::param_range
0257 #else
0258 clang::ArrayRef<clang::ParmVarDecl *>
0259 #endif
0260 functionParameters(clang::FunctionDecl *func);
0261 
0262 
0263 /**
0264  * For the given ctor, and ctor param, returns the ctor member initializers that used that param.
0265  * Example:
0266  * MyCtor(int a, int b) : c(a), d(b) {}
0267  * auto result = Utils::ctorInitializer(MyCtor, b); // Result is the statement "d(b)"
0268  */
0269 std::vector<clang::CXXCtorInitializer*> ctorInitializer(clang::CXXConstructorDecl *ctor,
0270                                                         clang::ParmVarDecl *param);
0271 
0272 /**
0273  * Returns true if a ctor initializer contains a std::move()
0274  * Example
0275  * MyCtor(Foo a) : c(move(a)) {} // Would return true for this init list
0276  */
0277 bool ctorInitializerContainsMove(clang::CXXCtorInitializer*);
0278 
0279 // Overload that recieves a vector and returns true if any ctor initializer contains a move()
0280 bool ctorInitializerContainsMove(const std::vector<clang::CXXCtorInitializer*> &);
0281 
0282 /**
0283  * Returns the filename for the source location loc
0284  */
0285 std::string filenameForLoc(clang::SourceLocation loc, const clang::SourceManager &sm);
0286 
0287 /**
0288  * Returns the location after the lexer token that is at loc.
0289  * For example:
0290  *     emit sig();
0291  * If loc refers to the location of 'emit', then this function will return the source location if
0292  * the sig() call.
0293  */
0294 clang::SourceLocation locForNextToken(clang::SourceLocation loc,
0295                                       const clang::SourceManager &sm,
0296                                       const clang::LangOptions &lo);
0297 
0298 inline bool isMainFile(const clang::SourceManager &sm, clang::SourceLocation loc)
0299 {
0300     if (loc.isMacroID())
0301         loc = sm.getExpansionLoc(loc);
0302 
0303     return sm.isInFileID(loc, sm.getMainFileID());
0304 }
0305 
0306 /**
0307  * Returns true if the string literal contains escaped bytes, such as \x12, \123, \u00F6.
0308  */
0309 bool literalContainsEscapedBytes(clang::StringLiteral *lt, const clang::SourceManager &sm, const clang::LangOptions &lo);
0310 
0311 /**
0312  * Returns true if this method overrides one from the base class
0313  */
0314 inline bool methodOverrides(clang::CXXMethodDecl *method)
0315 {
0316     return method && method->isVirtual() && method->size_overridden_methods() > 0;
0317 }
0318 }
0319 
0320 #endif