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