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

0001 /*
0002   This file is part of the clazy static checker.
0003 
0004     Copyright (C) 2018 Sergio Martins <smartins@kde.org>
0005 
0006     This library is free software; you can redistribute it and/or
0007     modify it under the terms of the GNU Library General Public
0008     License as published by the Free Software Foundation; either
0009     version 2 of the License, or (at your option) any later version.
0010 
0011     This library is distributed in the hope that it will be useful,
0012     but WITHOUT ANY WARRANTY; without even the implied warranty of
0013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014     Library General Public License for more details.
0015 
0016     You should have received a copy of the GNU Library General Public License
0017     along with this library; see the file COPYING.LIB.  If not, write to
0018     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019     Boston, MA 02110-1301, USA.
0020 */
0021 
0022 
0023 #ifndef SOURCE_COMPAT_HELPERS
0024 #define SOURCE_COMPAT_HELPERS
0025 
0026 #include <clang/AST/Attr.h>
0027 #include <clang/AST/Expr.h>
0028 #include <clang/AST/Decl.h>
0029 #include <clang/AST/DeclCXX.h>
0030 #include <clang/Basic/SourceLocation.h>
0031 #include <clang/Basic/SourceManager.h>
0032 #include <clang/Frontend/FrontendDiagnostic.h>
0033 #include <clang/Lex/Lexer.h>
0034 #include <clang/Tooling/Core/Diagnostic.h>
0035 
0036 #if defined(CLAZY_USES_BOOST_REGEX)
0037 # define BOOST_NO_EXCEPTIONS
0038 # include <boost/throw_exception.hpp>
0039 inline void boost::throw_exception(std::exception const &){}
0040 # include <boost/regex.hpp>
0041 using namespace boost;
0042 #else
0043 # include <regex>
0044 using namespace std;
0045 #endif
0046 
0047 namespace clazy {
0048 
0049 template <typename T>
0050 inline clang::SourceLocation getLocStart(const T *t)
0051 {
0052 #if LLVM_VERSION_MAJOR >= 8
0053     return t->getBeginLoc();
0054 #else
0055     return t->getLocStart();
0056 #endif
0057 }
0058 
0059 template <typename T>
0060 inline clang::SourceLocation getLocEnd(const T *t)
0061 {
0062 #if LLVM_VERSION_MAJOR >= 8
0063     return t->getEndLoc();
0064 #else
0065     return t->getLocEnd();
0066 #endif
0067 }
0068 
0069 inline clang::CharSourceRange getImmediateExpansionRange(clang::SourceLocation macroLoc, const clang::SourceManager &sm)
0070 {
0071 #if LLVM_VERSION_MAJOR >= 7
0072     return sm.getImmediateExpansionRange(macroLoc);
0073 #else
0074     auto pair = sm.getImmediateExpansionRange(macroLoc);
0075     return clang::CharSourceRange(clang::SourceRange(pair.first, pair.second), false);
0076 #endif
0077 }
0078 
0079 inline bool hasUnusedResultAttr(clang::FunctionDecl *func)
0080 {
0081 #if LLVM_VERSION_MAJOR >= 8
0082     auto RetType = func->getReturnType();
0083     if (const auto *Ret = RetType->getAsRecordDecl()) {
0084         if (const auto *R = Ret->getAttr<clang::WarnUnusedResultAttr>())
0085             return R != nullptr;
0086     } else if (const auto *ET = RetType->getAs<clang::EnumType>()) {
0087         if (const clang::EnumDecl *ED = ET->getDecl()) {
0088             if (const auto *R = ED->getAttr<clang::WarnUnusedResultAttr>())
0089                 return R != nullptr;
0090         }
0091     }
0092     return func->getAttr<clang::WarnUnusedResultAttr>() != nullptr;
0093 #else
0094     return func->hasUnusedResultAttr();
0095 #endif
0096 
0097 }
0098 
0099 inline clang::tooling::Replacements& DiagnosticFix(clang::tooling::Diagnostic &diag, llvm::StringRef filePath)
0100 {
0101 #if LLVM_VERSION_MAJOR >= 9
0102     return diag.Message.Fix[filePath];
0103 #else
0104     return diag.Fix[filePath];
0105 #endif
0106 }
0107 
0108 inline auto getBuffer(const clang::SourceManager &sm, clang::FileID id, bool *invalid)
0109 {
0110 #if LLVM_VERSION_MAJOR >= 12
0111     auto buffer = sm.getBufferOrNone(id);
0112     *invalid = !buffer.hasValue();
0113     return buffer;
0114 #else
0115     return sm.getBuffer(id, invalid);
0116 #endif
0117 }
0118 
0119 #if LLVM_VERSION_MAJOR >= 12
0120 
0121 #define GET_LEXER(id, inputFile, sm, lo) \
0122 clang::Lexer(id, inputFile.getValue(), sm, lo)
0123 
0124 #else
0125 #define GET_LEXER(id, inputFile, sm, lo) \
0126 clang::Lexer(id, inputFile, sm, lo)
0127 #endif
0128 
0129 inline bool isFinal(const clang::CXXRecordDecl *record)
0130 {
0131 #if LLVM_VERSION_MAJOR >= 11
0132     return record->isEffectivelyFinal();
0133 #else
0134     return record->hasAttr<clang::FinalAttr>();
0135 #endif
0136 }
0137 
0138 inline bool contains_lower(clang::StringRef haystack, clang::StringRef needle)
0139 {
0140 #if LLVM_VERSION_MAJOR >= 13
0141     return haystack.contains_insensitive(needle);
0142 #else
0143     return haystack.contains_lower(needle);
0144 #endif
0145 }
0146 
0147 }
0148 
0149 #endif